okta+react+openid認証 (2/2)

目的

okta+react+openid認証 を開発環境で実施してテストする。

長いためokta設定とreact設定で分けた。前の投稿はこちら

環境

  • react: 18.3.1
  • react-router:5.3.4
  • react-router-dom:5.3.4
  • @okta.okta-react:6.9.0
  • vite:6.0.5

react設定

公式GitHubレポジトリ github.com/okta/okta-react

oktaレポジトリインストール

Bash
npm install --save @okta/okta-react
Bash

OktaConfig.ts

oktaサーバーに接続する設定ファイルを作成する。設定ファイル.envを読み込む

src/OktaConfig.ts
const issuer = import.meta.env.VITE_APP_OKTA_ISSUER;
const clientId = import.meta.env.VITE_APP_OKTA_CLIENTID;
const redirectUri = import.meta.env.VITE_APP_OKTA_REDIRECTURI;

export interface OktaConfig {
    issuer: string;
    clientId: string;
    redirectUri: string;
    scopes: string[];
    pkce: boolean
}

export const oktaConfig: OktaConfig = {
    issuer: issuer,
    clientId: clientId,
    redirectUri: redirectUri,
    scopes: ['openid', 'profile', 'email'],
    pkce: true
}
TypeScript

.env

.env
VITE_APP_OKTA_ISSUER=https://{oktaサブドメイン}/oauth2/default
VITE_APP_OKTA_CLIENTID=XXXXXXXXXXXXXX
VITE_APP_OKTA_REDIRECTURI=http://localhost:8080/login/callback
INI

secure-route.tsx

認証が必要なページに対して付与する

src/secure-route.tsx
import { toRelativeUrl } from "@okta/okta-auth-js";
import { useOktaAuth } from "@okta/okta-react"
import React, { useEffect, useState } from "react";
import { Route, RouteProps, useRouteMatch } from "react-router-dom";

export type SecureRouteProps = {
    routeProps: RouteProps,
}

export const SecureRoute: React.FC<RouteProps> = ({ ...routeProps }) => {
    const { oktaAuth, authState } = useOktaAuth();
    const match = useRouteMatch();
    const isPending = React.useRef(false);
    const [error, setError] = useState<Error | null>(null);

    useEffect(() => {
        if (!match) { return; }
        if (!authState) { return; }
        if (authState.isAuthenticated) {
            isPending.current = false;
            return;
        }

        if (!authState?.isAuthenticated) {
            if (isPending.current) { return; }
            isPending.current = true;

            const originalUri = toRelativeUrl(window.location.href, window.location.origin);
            oktaAuth.setOriginalUri(originalUri);
            oktaAuth.signInWithRedirect();
        }


    }, [isPending, match, oktaAuth, authState, authState?.isAuthenticated]);

    if (error) {
        return <div>{error.message}</div>
    }

    if (!authState || !authState?.isAuthenticated) {
        return <div>Loading...</div>;
    }

    return (
        <Route
            {...routeProps}
        />
    )
}
TSX

routers.tsx

  • /
    • 認証が不要なページ
  • /login/callback
    • これがないと認証できない
  • /view
    • 認証が必要なページ
src/routers.tsx
import { Route, Switch, } from "react-router-dom"
import { LoginCallback, } from "@okta/okta-react";
import { SecureRoute } from "./secure-route";
import { View, Home } from "./routes/view";

const AppRouters = () => {

    return (
        <Switch>
            <Route path="/" exact component={Home} />
            <SecureRoute path="/view" component={View} />
            <Route path="/login/callback" render={() => (<LoginCallback />)} />
        </Switch>
    )
}

export default AppRouters;
TSX

index.tsx

src/index.tsx
import { useHistory } from "react-router-dom";
import { IonReactRouter } from '@ionic/react-router';
import AppRouters from "./routers"
import { Security } from "@okta/okta-react"
import { oktaConfig } from "@/OktaConfig";
import OktaAuth, { toRelativeUrl } from "@okta/okta-auth-js";

const oktaAuth = new OktaAuth(oktaConfig);

/** useHistoryはIonicRouter内部で使用しないとundefinedになるためwrap */
const SecurityWrapper = () => {
    const history = useHistory();
    const restoreOriginalUri = (_oktaAuth: unknown, originalUri: string) => {
        history.replace(toRelativeUrl(originalUri || '/', window.location.origin));
    };
    return (
        <Security oktaAuth={oktaAuth} restoreOriginalUri={restoreOriginalUri}>
            <AppRouters />
        </Security>
    )
}

export const App = () => {
    return (
        <Router>
            <SecurityWrapper />
        </Router>
    )
}
TSX

以上の内容でreactアプリを立ち上げ、SecureRouteで指定されているURLを入力するとOktaの認証画面が表示される。

認証に成功すると移動したかったページに移動できる。

以上

前の記事はこちら

コメントする