はじめに
ReactとKeycloakを連携し、OIDCによるログインを実装しましたので、実装方法についてご紹介しようと思います。
Open ID Connect(OIDC)
OIDCは、OAuthを拡張した認証のためのプロトコルで、シングルサインオン(SSO)に主に使われます。
OIDCの用語は以下になります。
- OpenID Provider(OP)
- ユーザの認証を行うサーバー。
- Relying Party(RP)
- OPにIDトークンとアイデンティ情報を要求するサーバー。
- UserInfoエンドポイント
- アクセストークンを示したクライアントに対し、アイデンティ情報を提供する。
- IDトークン
- 認証・認可の情報を含むJWT(JSON Web Token)形式のトークン。
- アクセストークン
-
UserInfo
エンドポイントにアクセスするためのトークン。
-
Keycloakの設定
今回、登録したKeycloakの設定を以下に示します。
- レルム:Keycloakでユーザなどの情報を管理するための単位。
- realm:
demo
- realm:
- クライアント:OIDCにおけるRPを指定します。
- Client ID:
demo-react-client
- RootURL:
http://localhost:3000/
- Client ID:
- ユーザー
- FirstName:
Foo
- LastName:
Smith
- Email:
user001@dummy.com
- Password:
password
- FirstName:
JavaScriptアダプター(keycloak.json)の設定
keycloak.json
で、JavaScriptアダプターの設定を行います。
javaScriptアダプターはKeycloakの機能であるクライアントアダプターの一つで、アプリケーションにOIDCのRPなどの機能を持たせることが可能です。KeycloakのClient
設定画面のInstallation
タブで「Format Option」にKeycloak OIDC JSON
を設定することでJSONファイルをダウンロードすることができます。
{
"realm": "demo",
"auth-server-url": "http://localhost:8080/auth/",
"ssl-required": "external",
"resource": "demo-react-client",
"public-client": true,
"confidential-port": 0
}
各設定内容については以下に示します。
-
realm
:レルム名 -
auth-server-url
:KeycloakのURL -
ssl-required
:SSLの設定-
external
:プライベートIPアドレスに固定する限り、ユーザーはSSL無しでKeycloakと通信可能。 -
none
:SSLの設定なし。 -
all
:すべてのIPアドレスに対し、SSLを要求。
-
-
resource
:クライアントの「Client ID」 -
public-client
:パブリッククライアントである場合はtrue
を設定
Reactでの実装
React 16.8
から追加された機能であるReact hooksを使い実装しました。
プロジェクト作成
Create React App
でプロジェクトを作成します。
$ npx create-react-app [プロジェクト名]
ディレクトリ構成
上記コマンドで作成されたディレクトリに追加したフォルダ・ファイルを示します。
public
ディレクトリに前述したkeycloak.json
を配置します。
また、src
ディレクトリにcomponents
ディレクトリを作成し、Secured.js
、Userinfo.js
、Logout.js
を配置します。
.
├── README.md
├── node_modules
├── package.json
├── public
│ ├── keycloak.json (追加)
│ ├── favicon.ico
│ ├── index.html
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├──components(追加)
│ │ ├── Secured.js
│ │ ├── Userinfo.js
│ │ ├── Logout.js
│ ├── App.css
│ ├── App.js
・
・
・
(省略)
Keycloakとの連携
import {React,useState,useEffect} from 'react'
import Keycloak from 'keycloak-js';
import UserInfo from './UserInfo';
import Logout from './Logout';
const Secured = () => {
const [keycloakState, setKeycloakState] = useState({ keycloak: null, authenticated: false });
useEffect(() => {
const keycloak = Keycloak('./keycloak.json');
//ページロード時の処理で、Keycloak.init関数を呼び出し、未認証の場合
//認可コードフローを開始しログインページを表示
keycloak.init({onLoad: 'login-required'}).then(authenticated => {
setKeycloakState({ keycloak: keycloak, authenticated: authenticated });
})
}, [])
console.log(keycloakState)
if(keycloakState.keycloak){
if(keycloakState.authenticated)
return (
<div>
<p>login success</p>
<UserInfo keycloak={keycloakState} />
<Logout keycloak={keycloakState} />
</div>
) ;
else
return(<div> 認証できません</div>)
}
return (
<div>Keycloakを初期化しています...</div>
)
}
export default Secured
http://localhost:3000/Secured
にアクセスし、確認します。
UseInfoの表示
import {useEffect,useState} from 'react'
const UserInfo = (props) => {
const keycloakState = props.keycloak
const [user, setUser] = useState({name:"",email:"",id:""});
useEffect(() =>{
//loadUserInfoから取得したユーザーデータを元にuserを更新
keycloakState.keycloak.loadUserInfo().then(UserInfo => {
console.log(UserInfo);
setUser({ name: UserInfo.name, email: UserInfo.email, id: UserInfo.sub })
});
},[])
return (
<div className="UserInfo">
<p>Name: {user.name}</p>
<p>Email: {user.email}</p>
<p>ID: {user.id}</p>
</div>
)
}
export default UserInfo
ここでは、Keycloakインスタンスから、loadUserInfo
メソッドを使用しユーザーデータの抽出をしています。
ログインが成功した後の画面に名前、メールアドレス、クライアントIDが表示されます。
ログアウトの実装
ここも同様に、Keycloakインスタンスからlogout
メソッドを使用します。
react-router
がv6
からuseHistory
メソッドが使用できなくなったため、useNavigate
メソッドを使用しログアウトを実装しました。
react-router
のv6
とv5
の違いについては、以下を参考にしてください。
import {React} from 'react'
import {useNavigate} from 'react-router-dom'
const Logout = (props) => {
const keycloakState = props.keycloak
// ログイン画面に遷移
const nabigate = useNavigate()
nabigate('/secured')
return (
<div>
<button onClick={ () => keycloakState.keycloak.logout()} >
Logout
</button>
</div>
)
}
export default Logout
まとめ
今回は、シンプルなReactアプリケーションとKeycloakを連携し、簡単にフロントエンドの認証を実装できることがわかりました。
Keycloakではシングルサインオンや外部プロバイダーを使った認証なども実装することができるので、色々活用してください。
# 参考
https://scalac.io/blog/user-authentication-keycloak-1/
https://blog.logrocket.com/implement-keycloak-authentication-react/