首页 > 解决方案 > OIDC客户端JS认证授权使用react应用

问题描述

我正在使用 OIDC 客户端使用 react 应用程序执行身份验证和授权。登录后我可以成功登录我有一个导航菜单来显示用户是否通过身份验证。

export default function NavMenu() {
    const authService = new AuthService();
    useSelector((state: ApplicationState) => state.oidcUser);
    const dispatch = useDispatch();
    const [state, setState] = useState({
        isLogedIn: false
    });
    const [open, setOpen] = React.useState(false);
    const close = () => {
        setOpen(false);
    };
    const menuClick =() => {
        setOpen(!open);
    };

    useEffect(() => {
        authService.getUser().then((user: any) => {
            if (user != null)
                setState({ isLogedIn: true });
            else
                setState({ isLogedIn: false })
        });

    });

    const login = () => {
        authService.startAuthentication(window.location.pathname);
    };
    const logout = () => {
        authService.logout();
    };

    const menuOptions = [
        'Save',
        'Edit',
        'Cut',
        'Copy',
        'Paste',
    ];

    return (<div>
        <TopAppBar>
            <TopAppBarRow>
                <TopAppBarSection align='start'>
                    <TopAppBarTitle>Falcon</TopAppBarTitle>
                </TopAppBarSection>
                <TopAppBarSection align='end' role='toolbar'>
                    <div>
                        {(() => {
                            if (!state.isLogedIn) {
                                return (
                                    <Button raised type="button" onClick={login}>Portal</Button>
                                )
                            } else {
                                return (
                                    <div>
                                        <Menu
                                            open={open}
                                            onClose={close}
                                            onSelected={(index, item) => console.log(index, item)}>
                                            <MenuList>
                                                {menuOptions.map((option, index) => (
                                                    <MenuListItem key={index}>
                                                        <MenuListItemText primaryText={option} />
                                                        {/* You can also use other components from list, which are documented below */}
                                                    </MenuListItem>
                                                ))}
                                            </MenuList>
                                        </Menu>
                                        <Fab onClick={menuClick} icon={<MaterialIcon icon="account_circle" />} />
                                    </div>
                                )
                            }
                        })()}
                    </div>
                </TopAppBarSection>
            </TopAppBarRow>
        </TopAppBar>
    </div>);
}

如果我使用该方法

useEffect(() => {
            authService.getUser().then((user: any) => {
                if (user != null)
                    setState({ isLogedIn: true });
                else
                    setState({ isLogedIn: false })
            });
        });

我从身份服务器获得了连接/检查会话 API 的无限循环。如果我删除该方法,则显示菜单的 if 条件 (state.isLogedIn) 将不起作用。

如何处理用户正确登录。在反应中进行 OIDC 客户端身份验证和授权的最佳方法是什么?

认证服务

export class AuthService {
    public userManager: UserManager;
    private user: any = null;

    constructor() {
        const settings = this.getClientSettings();
        this.userManager = new UserManager(settings);
    }


    public isLoggedIn(): boolean {
        return this.user != null && this.user.access_token && !this.user.expired;
    }

    public getUser(): Promise<User | null> {
        return this.userManager.getUser().then((user) => this.user = user);
    }

    public login(): Promise<void> {
        return this.userManager.signinRedirect();
    }
    public logout(): Promise<void> {
        return this.userManager.signoutRedirect(this.getClientSettings().post_logout_redirect_uri);
    }

    public startAuthentication(returnUrl: string) {
        Log.info("[AuthService] startAuthentication", returnUrl);
        this.userManager.clearStaleState();
        this.userManager.signinRedirect({ data: { returnUrl: returnUrl } }).then(user => this.user = user).catch(err => {
            this.handleError(err);
            return err;
        });
    }

    private getClientSettings(): any {
        return {
            authority: "https://localhost:5001",
            client_id: "Local",
            redirect_uri: "https://localhost:5001/auth-callback",
            post_logout_redirect_uri: "https://localhost:5001",
            response_type: "code",
            automaticSilentRenew: true,
            scope: "profile openid email IdentityPortal.API offline_access",
            //filterProtocolClaims: environment.openID.filterProtocolClaims,
            loadUserInfo: true,
            monitorSession: true,
            silent_redirect_uri: "https://localhost:5001/silent-reniew.html",
            accessTokenExpiringNotificationTime: 20, //default 60
            //checkSessionInterval: 86400, //default 2000
            //silentRequestTimeout: 2000,
        };
    }

    handleError(error: any) {
        Log.error(error)
    }
}

标签: reactjsasp.net-coreidentityserver4openid-connectoidc-client-js

解决方案


如果你想比较一些东西,也许看看我的 React 示例:

我的 AuthService 相当于我的Authenticator。如果您收到重定向循环,则可能是因为您没有调用 OIDC 客户端的 signInRedirectCallback() 方法来处理登录响应。我在您的代码中看不到对该调用的引用。


推荐阅读