今回は自作の認証プロバイダに接続するための認証利用アプリを実装していきます。「ReactでOpenID Connectを実装する~その4」ではAuth0に接続する認証利用アプリを実装しましたが、これを少しだけ修正して自作認証プロバイダに接続するようにします。

~目次~

認証利用アプリを修正する

事前準備

ReactでOpenID Connectを実装する~その4で作成したサンプルプログラム(authsample2)をコピーして、自作認証プロバイダに接続する認証利用アプリ(authsample3)を作ります。

(authsample2があるディレクトリに移動しておきます)

$ cp -r authsample2 authsample3

$ cd authsample3

 

トップ画面(index.js)

トップ画面にあたるindex.jsを次のように修正します。

import React from 'react';

import ReactDOM from 'react-dom';

import { AuthenticationProvider, oidcLog, InMemoryWebStorage } from '@axa-fr/react-oidc-context';

import './index.css';

import App from './App';

import reportWebVitals from './reportWebVitals';

 

// 認証プロバイダ(oidc-provider)に接続するためのパラメータ

const configuration = {

  authority: 'http://localhost:3001',

  client_id: 'SJvt23j8431D********************',

  redirect_uri: 'http://localhost:3000/authentication/callback',

  post_logout_redirect_uri: 'http://localhost:3000/',

  silent_redirect_uri: 'http://localhost:3000/authentication/silent_callback',

  response_type: 'code',

  scope: 'openid profile email api',

  automaticSilentRenew: true,

  loadUserInfo: true,

};

// ログ出力関数

const logger = {

  info: console.info,

  warn: console.warn,

  error: console.error,

  debug: console.debug,

};

// 認証プロバイダでのログインが成功し自サーバにリダイレクトされた時の表示処理

const CustomCallback = () => (

  <div><span>認証処理中...</span></div>

);

// 認証プロバイダでの認証が失敗し自サーバにリダイレクトされた時の表示処理

const NotAuthenticatedComponent = () => (

  <div><span>認証失敗しました。(Not Authenticated)</span></div>

);

// 認証プロバイダでの認可が失敗し自サーバにリダイレクトされた時の表示処理

const NotAuthorizedComponent = () => (

  <div><span>認可失敗しました。(Not Authorized)</span></div>

);

ReactDOM.render(

  <React.StrictMode>

    <AuthenticationProvider

      configuration={configuration}

      loggerLevel={oidcLog.DEBUG}

      logger={logger}

      isEnabled={true}

      callbackComponentOverride={CustomCallback}

      notAuthenticated={NotAuthenticatedComponent}

      notAuthorized={NotAuthorizedComponent}

      UserStore={InMemoryWebStorage}

    >

    <App />

    </AuthenticationProvider>

  </React.StrictMode>,

  document.getElementById('root')

);

reportWebVitals();

const configuration = { ... }

自作認証プロバイダに接続するための定義情報を設定します。

authority: 

自作認証プロバイダのドメイン(http://localhost:3001)を設定します。

client_id:

自作認証プロバイダで設定したClient IDを設定します。

redirect_uri:

'http://localhost:3000/authentication/callback'を設定します。

notAuthenticated={NotAuthenticatedComponent}

notAuthorized={NotAuthorizedComponent}

それぞれ認証失敗時・認可失敗時の表示内容を記載します。

 

index.js以外のソースは修正ありません。

動作確認

それでは実際に動かしてみます。authsample3ディレクトリ上で、Node.jsを起動します。

    (authsample3ディレクトリ内で)

    $ npm start

 

自動的にブラウザが起動します。もし起動しない場合には、http://localhost:3000/ にアクセスします。

最初はログイン認証できていない状態ですので、メイン部<App>でログインボタンを表示します。

 

ログインボタンを押下します。

すると、自作認証プロバイダにリダイレクトし、サインイン画面を表示します。

 

メールアドレスとパスワードには、ReactでOpenID Connectを実装する~その6においてaccount.jsで定義したユーザIDとパスワードを入力します。

正しいユーザIDとパスワードを入力すると、次に認可確認画面(Authorize画面)が表示されます。

 

ここでContinueボタンを押下すると、自サイト(localhost:3000)にリダイレクトされ、ダミー画面が表示されます。

そしてダミー画面の表示処理の裏では、自サイトから自作認証プロバイダにトークンリクエストを投げてアクセストークンを取得しています。認証後の画面を表示します。

 

Logoutボタンを押下すると、ログアウト処理が行われ、再び最初のログイン画面に戻ります。

 

(参考)ClientTypeによる認証方法の使い分け

OpenID Connectの規格にはClient Typeとよばれる設定値があり、publicかconfidentialかどちらかを選択することができます。publicが簡易的な方法、confidentialが厳密な方法になります。

Client Type = publicの場合

今回の作成したサンプルはこのパターンで実装しています。

認証プロバイダでは、token_endpoint_auth_methodの値を 'none' とし、Client Typeがpuclicであることを示します。client_secretは指定しません。

  clients: [

     {

       client_id: 'SJvt23j8431D********************',

       // client_secret: '7fa_dVrC********************',

       grant_types: ['refresh_token', 'authorization_code'],

       redirect_uris: ['http://localhost:3000/authentication/callback'],

       post_logout_redirect_uris: ['http://localhost:3000/'],

     }

  ],

  clientDefaults : {

    token_endpoint_auth_method: 'none',

  },

...以下略...

 

一方、認証利用アプリでも、以下のようにclient_secretやclient_authenticationを指定しません。

const configuration = {

  authority: 'http://localhost:3001',

  client_id: 'SJvt23j8431D********************',

  redirect_uri: 'http://localhost:3000/authentication/callback',

  //  client_secret: '7fa_dVrC********************',
  //  client_authentication : 'client_secret_basic',

  ...以下略...

 

Client Type = confidentialの場合

より厳密な認証をしたい場合には、このパターンを選びます。

認証プロバイダでは、token_endpoint_auth_methodの値を 'client_secret_basic' とし、Client Typeがconfidentialであることを示します。client_secretとして任意の文字列を指定します。

  clients: [

     {

       client_id: 'SJvt23j8431D********************',

       client_secret: '7fa_dVrC********************',

       grant_types: ['refresh_token', 'authorization_code'],

       redirect_uris: ['http://localhost:3000/authentication/callback'],

       post_logout_redirect_uris: ['http://localhost:3000/'],

     }

  ],

  clientDefaults : {

    token_endpoint_auth_method: 'client_secret_basic',

  },

...以下略...

 

一方、認証利用アプリは、以下のようにclient_secretやclient_authenticationを指定します。

const configuration = {

  authority: 'http://localhost:3001',

  client_id: 'SJvt23j8431D********************',

  redirect_uri: 'http://localhost:3000/authentication/callback',

  client_secret: '7fa_dVrC********************',
  client_authentication : 'client_secret_basic',

  ...以下略...

当然ですが、認証利用アプリのclient_secret値と認証プロバイダのclient_secrect値が一致していないと認証エラーとなります。

 

 

最後はOpenID Connectとはまったく無関係なあとがきです。

ReactでOpenID Connectを実装する~その8 あとがき