ユーザ認証とアクセス権の設定をサポートします。INTER-Mediator自身がデータベースを利用して、ユーザーやグループを管理する手法を「ビルトイン認証」、SAMLを利用する認証を「SAML認証」と呼びます。また、OAuth2(ただし、Googleのみ確認)にも対応しています。INTER-Mediator Ver.8では、パスワード記録時のハッシュを従来のSHA-1から、5000ストレッチしたSHA-256にアップデートしています。従来のSHA-1でのハッシュと相互運用もできます。LDAPについては、SAMLのIdp経由でSAMLベースで利用するようになりました。本ページは、INTER-Mediator Ver.14の状況で説明しています。

認証動作に必要なテーブル

チャレンジ等を記録するテーブル

ユーザ認証ではセキュリティを高めるために、サーバーからクライアントに「チャレンジ」を送り、その値を利用して認証情報を作ります。そのため、サーバー側にチャレンジを残しておく必要があり、テーブルの定義が必要です。そのテーブルは、IM_Entryの第3引数あるいはparams.phpで指定したユーザで読み書きの権限が必要です。チャレンジのテーブル名は、IM_Entryの第2引数で指定するか、あるいは既定値の名前(issuedhash)のテーブルを作成します。テーブルには以下のフィールドが必要です。

チャレンジのテーブルに必要なフィールド
フィールド名 型の例 説明
id INT AUTOINCREMENT、連番の数値を入れて、キーフィールドとする
user_id INT, ユーザテーブルのキーフィールドとなるid値(ユーザをデータベース内のテーブルで管理する場合に利用)
clienthost VARCHAR(64), クライアントを識別する情報。サーバーからランダムに与えられる40バイトのHEXコード。ただし、パスワードのセルフサービスのリセット時にSHA-256のハッシュ値のHEX文字列が入る。
hash VARCHAR(64), チャレンジに使うハッシュ値。実際には48バイトの16進数文字列。ただし、パスワードのセルフサービスのリセット時にSHA-256のハッシュ値のHEX文字列が入る。
expired DateTime, チャレンジの有効期限を示すタイムスタンプ値

なお、このテーブルへの検索では、user_idとclienthostの2つのフィールドに対してAND演算での検索条件が与えられます。従って、高速化するためには、この2つのフィールドを合成したインデックスを作っておきます。

ユーザーのテーブル

認証のためのユーザは、データベース内にテーブルを作成する方法と、データベースエンジンが管理するユーザによる方法を利用できます。データベース内にテーブルを作る場合、そのテーブルは、IM_Entryの第3引数あるいはparams.phpで指定したユーザで少なくとも読み出しの権限が必要です。チャレンジのテーブル名は、IM_Entryの第2引数で指定するか、あるいは既定値の名前(authuser)のテーブルを作成します。テーブルには以下のフィールドが必要です。

ユーザテーブルに必要なフィールド
フィールド名 型の例 説明
id INT AUTO_INCREMENT。連番の数値を入れて、キーフィールドとする
username VARCHAR(64) ユーザ名(特に制限はないが、重複した名前が定義されないようにするのが望ましい)
realname VARCHAR(20) 利用者名で、認証には特には関係ないのでなくても構わないが、SAMLやOAuth2では得られることが多く文字列として記録しておく
hashedpasswd VARCHAR(72) パスワードのハッシュ値。SHA-256のハッシュ値と、4バイトのソルトを合成したコードのHEXが入るので、72バイト必要。
email VARCHAR(100), 電子メールアドレス。ユーザー名の代わりに使用したり、パスワードのリセットで利用
limitdt DateTime LDAP認証ユーザーのキャッシュの期限

ユーザの場合は、ユーザ名をキーフィールドに使えるとも考えられますが、大量のユーザになったときなどに処理速度を有利にするために、内部的にはidフィールドによる連番で与えた数値で処理をすることにします。なお、usernameを条件として検索をかけるので、高速化のためにはこのフィールドにインデックスを作成しておきます。パスワードはハッシュを保存しますが、ハッシュ値は、次の手順で計算をします。

  1. パスワード(pw)と、4バイトのソルト(s)を用意します。
  2. パスワードとソルトをつなげた文字列のSHA-256を5000回のストレッチで求めます( sha256(pw+s, 5000) → H1)
  3. H1の16進数表現した文字列と、ソルトを16進数表現した文字列をつなげます(hex(H1)+hex(s)→H2)
  4. H2をフィールドに保存します。

コマンドで求める例としては、あまり効率良くはないですが、INTER-Mediatorのレポジトリにあるdist-docs/passwdgen.shスクリプトを利用できます。-uはユーザ名、-pはパスワード、-sはSQL文として出力するパラメータです。opensslのコマンドを内部で使っていますが、5000回のストレッチをコマンドから行う方法がわからず、シェルスクリプトで繰り返してopensslコマンドを動かしているため、ハッシュの計算に30秒から1分くらいかかると思われます。

% dist-docs/passwdgen.sh -u test -p TEST -s
INSERT authuser(username,initialpass,hashedpasswd) VALUES('test','TEST','5d4b09daced104e42bc5cfc1d4db6c677afd3ffeadc950a2873b009aeba39bab45654d4b');

なお、過去に開発したアプリケーションとの互換性を考慮して、SHA-1での利用も可能です。SHA-1ハッシュ値は、次の手順で計算をします。

  1. パスワード(pw)と、4バイトのソルト(s)を用意します。
  2. パスワードとソルトをつなげた文字列のSHA-1求めます( sha1(pw+s) → H1)
  3. H1の16進数表現した文字列と、ソルトを16進数表現した文字列をつなげます(hex(H1)+hex(s)→H2)
  4. H2をフィールドに保存します。

SHA-256互換ハッシュという、SHA-1からパスワードを変更せずにハッシュそのものはSHA-256に移行できるモードも用意しています。設定を行えば、SHA-1での認証が成功した時に、データベースのhashedpasswdフィールドの内容をこの互換ハッシュで書き換えます。次回以降の認証は、互換ハッシュを使っての認証となるので、パスワードを変更せずにSHA-256を使ったハッシュでの運用に移行できます。互換ハッシュは次の手順で計算をします。

  1. SHA-1で求めたHEX表現のハッシュをHとします。
  2. Hのソルトを求めてsとします(salt(H) → s)
  3. Hとsをつなげた文字列のSHA-256を5000回のストレッチで求めます( sha256(H+s, 5000) → H1)
  4. Hの16進数表現した文字列と、ソルトを16進数表現した文字列をつなげます。このH2がSHA-256互換ハッシュです(hex(H1)+hex(s)→H2)

グループを管理するテーブル

グループそのものを管理するテーブルと、ユーザーやグループの特定のグループへの所属を記録するテーブルの2つがあります。

グループテーブル(既定名:authgroup)のフィールド
フィールド名 型の例 説明
id INT AUTO_INCREMENT,グループを識別するための番号
groupname VARCHAR(48), グループ名
ユーザ・グループ対応付けテーブル(既定名:authcor)のフィールド
フィールド名 型の例 説明
id INT AUTO_INCREMENT、主キーフィールド
user_id INT, 所属するユーザのidフィールドの値
group_id INT, 所属するグループのidフィールドの値
dest_group_id INT, 所属されるグループのidフィールドの値

アクセス権に関する設定の評価

認証の設定は基本的にコンテキストに行いますが、IM_Entryの2番目の引数にも行えます。記述可能な内容については、『定義ファイルでの記述方法a>』を参照してください。つまり、2カ所の設定があるので、以下のように、コンテキストに設定する方を「コンテキストの認証設定」、2つ目の引数に設定するのを「オプションの認証設定」とします。また、いずれも、アクセス権の設定も行いますが、「認証とアクセス権」を合わせてここでは「認証」というネーミングをします。

IM_Entry(
    array(
        array(
            "name"=>"context",
            "authentication"=>array(
                /* コンテキストの認証設定 */
            ),
        ),
    ),
    array(
        "authentication"=>array(
            /* オプションの認証設定 */
        ),
...);

オプションの認証設定やparams.phpファイルに設定可能な情報

オプション配列に関して(未定義)とあるものは、オプションで指定ができないものを意味します。つまり、この設定は、params.phpファイルでの変数での設定のみです。一方、params.phpでの変数名が(未定義)のものは、オプション設定のみで利用できるものです。既定値が「なし」とは、設定しない場合はその機能が利用できないことを意味します。

認証設定の動作に関する設定

オプション配列指定 params.phpでの変数名 既定値 設定の説明
第1次元 第2次元
'authentication' 'user' (未定義) なし 利用可能なユーザを配列で指定。この記述がなければすべてのユーザにアクセス権。データベースのネイティブユーザで認証する場合には、値を「array('database_native')」と指定する。
'group' (未定義) なし 利用可能なグループを配列で指定。この記述がなければすべてのグループにアクセス権
'authexpired' $authExpired 3600 認証が自動的に継続される時間を秒数で指定する。省略すると'3600'(1時間)。バージョン4.4以降では、0を指定すると有効期限はWebブラウザー終了時まで
(未定義) $defaultGroupName なし グループに全く所属しないユーザの場合、ここで指定した文字列のグループに所属しているものとして扱う。このグループはauthgroupに登録されてなくても良い
'storing' $authStoring 'credential' 認証情報のクライアントへの保存を指定。'session-storage'ならブラウザのセッションストレージに保存、'credential'であれば認証情報をhttp-onlyのクッキーに保存する
'realm' $authRealm '' 認証領域名。ログインパネルの上部に表示される。また、認証情報を記憶するクッキーの名称の末尾に付与される。
'email-as-username' $emailAsAliasOfUserName false trueを指定すると、authuserテーブルのusernameと同時にemailフィールドも検索する。つまり、電子メールアドレスでの認証が可能になる。
(未定義) $passwordHash "1" "1"なら、SHA-1、SHA-256互換、SHA-256のいずれも対応。"2m"なら、SHA-256互換、SHA-256のいずれも対応。"2"なら、SHA-256のみ対応。
(未定義) $alwaysGenSHA2 false $passwordHashが"1"で、この変数がfalseの場合、パスワード変更するとSHA-1でハッシュする。この変数がtrueなら、パスワード変更時にSHA-256でハッシュする。$passwordHashが"1"以外の場合は、この変数に関係なく、パスワードを変更すると、SHA-256でハッシュをかける。
(未定義) $migrateSHA1to2 false trueにすれば、SHA-1でハッシュされたパスワードでログインをした後、そのハッシュ値をSHA-256互換のハッシュにコンバートする。実質的に、SHA-1のパスワードを変更しないでSHA-256に移行できる。
is-required-2FA $isRequired2FA false 二要素認証を有効にする。ユーザ名とパスワードの認証に加えて、メールで送られたコードの入力を必要とするため、authuserテーブルのemailフィールドに正いメールアドレスが入力されていることが必要
mail-context-2FA $mailContext2FA なし 二要素目となるコードを送信するメールのコンテキスト。例えば、"mailtemplate@id=995"など。サンプルデータベースのmailtemplateテーブルにあるid=995の内容を参考にできる
expiring-seconds-2FA $expiring2FA 1000 二要素認証のコード入力が有効な時間を秒数で指定する。
digits-of-2FA-Code $ditigsOf2FACode 4 二要素認証のコードの桁数。なお、コードは数字のみを使う
(未定義) $fixed2FACode なし ここで数値によるコードを文字列で指定すると、二要素目の認証での正いコードは、常にここで指定したコードになる。二要素認証のテスト等で利用することを想定しており、実利用のためのものではない

認証動作に関する設定

オプション配列指定 params.phpでの変数名 既定値 設定の説明
第1次元 第2次元
'authentication' 'user-table' (未定義) 'authuser' ユーザ情報が保存されているテーブル名
'group-table' (未定義) 'authgroup' グループ情報が保存されているテーブル名
'corresponding-table' (未定義) 'authcor' ユーザとグループが対応づけられている情報が保存されているテーブル名
'challenge-table' (未定義) 'issuedhash' チャレンジが保存されているテーブル名
'issuedhash-dsn' $issuedHashDSN なし issuedhashテーブルに対するDSNを指定する。たとえば、FileMakerデータベースで、issuedhashテーブルをSQLiteで運用する場合に使える
'password-policy' $passwordPolicy '' パスワード変更時に適用されるパスワードポリシー。useAlphabet useNumber useUpper useLower usePunctuation length(10) notUserName の各単語をスペースで区切って指定する。useAlphabetはアルファベットを使用していないといけなくする。その他、同様に単語から意味が分かるはずである。length(10)はパスワードは10文字以上にする必要があるという意味で、( ) 内には任意の数値を記述できる。
'reset-page' $resetPage なし ログインパネルに、パスワードリセットページへのボタンを設置する。ここに、パスワードリセットページのURLを記載する。
'enroll-page' $enrollPage なし ログインパネルに、ユーザー登録ページへのボタンを設置する。ここに、ユーザー登録ページのURLを記載する。
(未定義) $suppressDefaultValuesOnCopy false レコードの複製を行うときに、新規レコードの既定値を適用しないようにする。認証だけに関係するわけではないがリレーションシップのキーフィールドに複製が重複してかからないようにすることが期待できる。
(未定義) $suppressDefaultValuesOnCopyAssoc false 関連レコードの複製を行うときに、新規レコードの既定値を適用しないようにする。認証だけに関係するわけではないがリレーションシップのキーフィールドに複製が重複してかからないようにすることが期待できる。
(未定義) $suppressAuthTargetFillingOnCreate false レコードを作成するときに新規レコードの既定値を適用しないようにする。認証だけに関係するわけではないがリレーションシップのキーフィールドへの入力が重複してかからないようにすることが期待できる。

OAuth2認証に関する設定

params.phpで変数名 設定する値
$oAuth OAuth認証の設定を行う指定する文字列で、プロバイダ名をキーとした連想配列を指定する。値も連想配列(以下に記述)。プロバイダ名は "Google" "Facebook"に対応。
$oAuth/Google/AuthButton ログインパネルに配置されるOAuth認証に移行するためのボタンの名前 [Google, Facebook]
$oAuth/Google/ClientID プロバイダから供給されるクライアントID [Google, Facebook]
$oAuth/Google/ClientSecret プロバイダから供給されるシークレット [Google, Facebook]
$oAuth/Google/RedirectURL 認証後に戻ってくるリダイレクトURL [Google, Facebook]

SAML認証についての設定

配列指定 params.phpで変数名 既定値 設定の説明
第1次元 第2次元
'authentication' is-saml $isSAML false SAML認証を有効にする。なお、SAMLのSPになるための設定については、INTER-Mediatorのレポジトリにあるsample/saml-configディレクトリの内容と説明を参照してください。
(未定義) $samlAuthSource なし SPの識別名
(未定義) $samlExpiringSeconds 3600 SAML認証をキャッシュした場合のキャッシュの有効秒数
saml-builtin-auth $samlWithBuiltInAuth false trueにすると、SAML認証だけでなく、ビルトイン認証も並行して利用できる。そのため、INTER-Mediatorのログインパネルが表示され、そこに「SAML認証」ボタン(ボタン名のメッセージの番号は2026)が表示される
(未定義) $samlAttrRules なし SAML認証時に得られる情報から、ユーザ名などを抜き出すルールを記述する
(未定義) $samlAdditionarlRules なし SAMLで得られたユーザ情報が特定の値になっていない場合に認証を不成立とすることができ、そのルールをここに記述する

ログインパネルのカスタマイズに関する設定

params.phpで変数名 設定の説明
$extraButtons 連想配列のキーがボタン名、値がリンク先のURLとして、連想配列を指定することで、ログインパネルに別のページを表示するボタンを作成できる。
$resetPage URLを文字列で指定すると、ログインパネルに「パスワードをリセット」のボタンが表示され、クリックするとそのURLへジャンプする。ボタン名のメッセージの番号は2023
$enrollPage URLを文字列で指定すると、ログインパネルに「ユーザー登録をする(要メールアドレス)」のボタンが表示され、クリックするとそのURLへジャンプする。ボタン名のメッセージの番号は2022
$authPanelTitle ログインパネルに表示するタイトル
$authPanelTitle2FA 二要素認証の入力パネルに表示するタイトル
$authPanelExp ログインパネルに表示する説明文
$authPanelExp2FA 二要素認証の入力パネルに表示する説明文
$limitEnrollSecond ログインパネルに表示する説明文
$limitPwChangeSecond 二要素認証の入力パネルに表示する説明文

コンテキストの認証設定に設定可能な情報

配列指定 設定の説明
キー インデックス 下位のキー
'authentication' 'media-handling' メディアアクセス時の認証を通すためのクッキー情報を、このコンテキストの読み出し時にクライアントに送り込む。必要なときに値にtrueを指定する
'all' 'user' すべての操作について、このコンテキストを利用可能なユーザを配列で指定。この記述がなければすべての認証ユーザにアクセス権
'group' すべての操作について、このコンテキストを利用可能なグループを配列で指定。この記述がなければすべてのグループにアクセス権
'target' 省略あるいは'table'なら、テーブル全体に対する権限の設定、'field-user'あるいは'field-group'ならレコードごとに権限を指定できる
'field' 'target'に'field-user'あるいは'field-group'に指定した場合、ユーザ名やグループ名を指定するフィールドのフィールド名
'noset' 'noset' => trueで指定すると、レコード作成時に、fieldで指定したフィールドにユーザ名あるいはグループ名を設定する操作を行わない。例えば、認証に使うフィールドを意図的にリレーションシップにより自動的に設定するようなことを意図した場合、リレーションシップのためのフィールド設定と、fieldに指定したフィールドへの入力が重複してSQLエラーが出る。それを回避するための設定。
'read' (allと同様) クエリーの操作について、このコンテキストに関する設定を行う
'update' (allと同様) 更新の操作について、このコンテキストに関する設定を行う
'create' (allと同様) 新規レコード作成の操作について、このコンテキストに関する設定を行う
'delete' (allと同様) レコード削除の操作について、このコンテキストに関する設定を行う
'protect-writing' この配列に指定したフィールド名に対する更新処理を禁止する
'protect-reading' この配列に指定したフィールド名から読み出したデータをクライアントに送る事を禁止する

コンテキストの認証設定なし、オプションの認証設定あり

タイトル用な条件だと、コンテキストの認証設定のuserとgroupがアクセス権の設定に関係します。もし、userもgroupも設定されていない場合は、認証が通ったユーザは何でもできると考えてください。

userあるいはgroupが設定されている場合、認証が通ると同時に、そのユーザあるいはそのユーザを含むグループが、userあるいはgroupの設定に含まれている必要があります。

コンテキストの認証設定あり、オプションの認証設定なし

オプションの設定のうちuserとgroupの設定がないということです。この場合、特定のコンテキストのデータベース処理に対して、コンテキストの認証設定が適用されます。

コンテキストの認証設定あり、オプションの認証設定あり

両方の認証設定があれば、先にオプションの認証設定が評価されて、その後にコンテキストの認証設定が評価されます。

コンテキストの認証設定の適用対象

適用対象として、4つのデータベース処理、read/create/update/deleteに対する処理と、それらすべてに対してまとめて設定を行うallがあります。

コンテキストの認証設定のtableとfleld

"table"キーに対する値がfield-userあるいはfield-groupの場合は、そのテーブルにあるfieldに指定したフィールドに、ログインが成功したユーザあるいはそのユーザが含むグループの名前が設定されちているレコードだけに絞り込まれます。検索条件にANDでユーザないしはグループの値をfieldに指定したフィールドに対する条件を付け加えます。したがって、fieldで指定したフィールドのうち、空欄ものは認証すればいっさいアクセスできないということになります。

"table"キーに対する値がfield-useやfield-groupではない場合、アクセス権はすべてのテーブルに渡って適用されます。レコードごとのアクセス権を記録するフィールドは不要です。このとき、userあるいはgroup属性に含まれていないユーザで認証した場合、いっさいのアクセスはできないようになっています。オプションの認証設定と異なる動作ですので、注意してください。

read/update/deleteに関しては、アクセス権は「検索条件」として集約されます。一方、createの操作に対しては、アクセス権がある場合だけ、レコードの作成が可能です。レコードの作成により、fieldで指定したフィールドに、ユーザないしはグループが設定されます。ユーザの場合は1つに決まりますが、グループの場合は、グループ名を並べ替えたときのいちばん先頭のグループ名を記録するようにします。

ログインパネルのカスタマイズ

ログインパネルのカスタマイズについて、マイナーなものであれば、CSSの設定で行けると思います。ブラウザのデバッガで見ていただければ、ログインパネルの各要素はそれぞれclass属性が割り当てられているので、たとえば、ページのヘッダや独立したファイルでCSSを適用します。これらは、原則としてINTER-Mediatorのテーマ設定よりも優先度は高くなるので、上書きや変更は可能です。なお、ログインパネルのスタイル情報はテーマに含まれているので、テーマを作り直すという方法もあります。

ログインパネルを完全にカスタマイズしたいとう場合は、例えば、以下のようなプログラムを、INTERMediatorOnPage.doBeforeConstructに代入する関数の中などで実行します。最初の3行はプロパティ名から動作は明白と思われますが、ポイントは、ページに上乗せするログインパネル部分を、HTMLの文字列として、loginPanelHTMLプロパティに書き込みます。

INTERMediatorOnPage.isShowChangePassword = false;
INTERMediatorOnPage.defaultBackgroundImage = null;
INTERMediatorOnPage.defaultBackgroundColor = "white";
INTERMediatorOnPage.loginPanelHTML = '<div>....';

このloginPanelHTMLに書き込むHTMLはボディの一部となるような書き方をします。原則自由に記述できますが、この中にユーザー名を入れるテキストフィールドや、認証ボタンなどを配置する必要があります。それらは、決められたid属性を持つ必要があります。INTER-Mediatorが認識するid属性は、_im_password、_im_username、_im_authbutton、_im_changebutton、_im_oauthbuttonです。最初の2つがテキストフィールド、残りがボタンを想定しています。このid属性値を設定しておけば、例えば、認証ボタンとしての機能はINTER-Mediatorが自動的に組み込みます。