技術情報・ダウンロード

 お問い合わせ

株式会社セシオス

〒171-0022
東京都豊島区南池袋2-13-10 南池袋山本ビル 3F
TEL : 03-6265-0448

フォームからのお問い合わせ

SlinkOTPによるワンタイムパスワード認証

ワンタイムパスワードソフトウェアSlinkOTPのインストール手順について解説します。 SlinkOTPは、時刻同期式のワンタイムパスワードで、アルゴリズムにRFC標準のOATHを採用しています。

SlinkOTPは以下からダウンロードして下さい。

1. 認証サーバのインストール

1.1 環境
1.2 必要なソフトウェアのインストール

epelをyumリポジトリに追加してから、次のソフトウェアをインストールして下さい。

ionCube loaderを http://www.asial.co.jp/ioncube/encoder/download_loaders.php からダウンロードして、インストールして下さい。

1.3 SlinkOTP認証サーバのインストール

SlinkOTP認証サーバダウンロードして下さい。 ダウンロードしたファイルを展開して、インストールスクリプトを実行して下さい。

# tar zxvf slink-otp-1.0.x.tgz
# cd slink-otp-1.0.x
# ./install.sh install

1.4 ログの設定

“/etc/rsyslog.conf”に以下の設定を追加して下さい。

local5.*     /var/log/auth.log

2. コンシューマサイトで使用する場合

2.1 MySQLの設定

データベースotp_dbを作成して、SlinkOTPに収録されているSQLファイル”otpuser.sql”をDBサーバに登録して下さい。

# mysql –user=dbuser –password=dbpasswd otp_db < conf/otpuser.sql

2.2 SlinkOTP認証サーバの設定

“/var/www/conf/config.ini-consumer”を”/var/www/conf/config.ini”に置き換え、環境に合わせて変更して下さい。

[password]
storage = “DB”
dsn = “mysql://<DBに接続するユーザ>:<DBに接続するパスワード>@<DBのホスト名>/otp_db”
table = user_tbl
idcol = user_id
usercol = user_id
mailcol = mail
secretcol = otp_secret
keyfile = “/var/www/conf/auth_tkt.conf”

[otp]
pwmaxfailure = 30 ;アカウントをロックするまでの認証失敗回数
pwfailureinterval = 600 ;認証失敗回数をカウントする期間
pwloduration = 1800 ;アカウントロックを解除するまでの時間
auto_register = 1

次に”/var/www/conf/auth_tkt.conf”に暗号化キーの設定を行います。SlinkOTPはワンタイムパスワードのシークレットを暗号化してDBに保存しますので、その際の暗号化にこのキーを使用します。

TKTAuthSecret <任意の文字列>

“/var/www/conf/sam.conf”を環境に合わせて変更して下さい。

dsn = “DBI:mysql:database=otp_db;host=<DBのホスト名>;port=3306″
admin = “<DBに接続するユーザ>”
passwd = “<DBに接続するパスワード>”
table = “user_tbl”
id_def = “user_id”
pwd_def = “password”
memcache_host = <memcachedのホスト名:ポート番号>
maildir = /var/www/conf/mail
is_api = 1

“/var/www/conf/mail/config.ini”にメールサーバの設定を行って下さい。

postmaster = “<送信元メールアドレス>”
smtp = “<メールサーバのホスト名>”
smtpauth_user = “”
smtpauth_pass = “”

また、”/var/www/conf/mail/motp.mail”にワンタイムパスワードを送信するメールのテンプレートがありますので、適宜内容を変更して下さい。

2.3 ユーザによるワンタイムパスワードの設定

ユーザがワンタイムパスワード認証の開始、停止を設定する機能です。

ユーザがワンタイムパスワード認証の開始、停止を設定するには、コンシューマサイトでユーザの認証を行った際に、ユーザの認証情報としてユーザIDとメールアドレスを以下の形式でmemcachedに登録しておく必要があります。

erName=<ユーザID>\r\nmail=<メールアドドレス>\r\nauthenticated=0\r\n

memcachedに認証情報を登録した際のキーは、”AuthMemCookie”という名前のクッキーにセットして、ユーザに発行して下さい。

以下は、Basic認証でユーザを認証した場合のサンプルプログラムです。”slinkotp.php”は、SlinkOTPの”devel”フォルダに収録されています。

<?php
session_start();
require_once('slinkotp.php');
$dsn = 'mysql:host=localhost;dbname=otp_db';
$dbuser = 'root';
$dbpasswd = 'password';
if (isset($_SERVER['REMOTE_USER'])) {
    $userid = $_SERVER['REMOTE_USER'];
    $mail = $_SERVER['REMOTE_USER'];
    $sessid = setSession(array('127.0.0.1'), $userid, $mail);
    $_SESSION['userid'] = $userid;
    try {
        $type = getOtpType($dsn, $dbuser, $dbpasswd, $userid);
    } catch (Exception $e) {
        print($e->getMessage()."<br>");
        exit(1);
    }
    // ==================== OTP省略 ====================
    if (isset($_COOKIE['auth_otp']) && $_COOKIE['auth_otp']) {
        $url = "https://localhost/pub/psession.php";
        $timeout = 3;
        $postdata = "sessid=".urlencode($_COOKIE['auth_otp'])."&useragent=".urlencode($_SERVER['HTTP_USER_AGENT']);
        $response = getContentsByUrl($url, $timeout, $postdata);
        // 登録成功であれば、クッキーを発行する
        if (preg_match('/<code>([^<]*)<\/code>[^<]*<message>([^<]*)<\/message>[^<]*<id>([^<]*)<\/id>[^<]*<sessid>([^<]*)<\/sessid>/', $response, $matches)) {
            $code = $matches[1];
            $message = $matches[2];
            $id = $matches[3];
            $newsessid = $matches[4];
            if ($id && $id == $userid) {
                $type = 0;
                if ($newsessid) {
                    setcookie("auth_otp", $newsessid, time()+36000, '/');
                }
            }
            else {
                //
            }
        }
        else {
            $message = $response;
        }
        print("<br>response: $response<br>code: $code<br>message: $message<br>id: $id<br>newsessid: $newsessid<br>");
    }
    // ==================== OTP省略 ====================
    switch ($type) {
      case 1:   //SeciossOTP
        header('Location: otplogin.php');
        exit(0);
        break;
      case 2:   //e-mail
        header('Location: motplogin.php');
        exit(0);
        break;
      case 3:   //Google Authenticator
        header('Location: otplogin.php');
        exit(0);
        break;
      default:
        print("ログインしました。<br>sessid: $sessid");
        setAuthenticated(array('localhost'), $sessid);
    }
}
?>

また、”/etc/httpd/conf.d/otp.conf”の”ErrorDocument 401″に上記のプログラムのURLを設定して下さい。

認証後は、”https://<認証サーバのホスト名>/user/”にアクセスすると、ワンタイムパスワードの設定画面が表示されます。

ユーザによるワンタイムパスワードの設定

パスワードの受け取り方法でスマートフォンアプリを利用する場合は、iPhoneについてはApp Storeから、AndroidについてはGoogle Playから”SlinkOTP”を検索して、ダウンロードして、SeciossLinkユーザガイドの”4.5 ワンタイムパスワードのシークレットキー登録”の手順に従って、シークレットの登録を行って下さい。

パスワードの受け取り方法でメールを選択した場合、memcachedに登録されているメールアドレス(mail)にワンタイムパスワードが送信されるようになります。

3. 企業で使用する場合

3.1 OpenLDAPの設定

slink-otp-1.0.x内のスキーマファイルを、OpenLDAPにコピーして下さい。
# cp conf/secioss.schema /etc/openldap/schema

OpenLDAPの設定ファイル”/etc/openldap/slapd.conf”に次の設定を追加して下さい。

include /etc/openldap/schema/secioss.schema

ユーザ情報の登録を行います。ユーザのobjectClassにはseciossOtpUserを追加して下さい。
例えば、以下のようなLDIFをLDAPサーバに登録して下さい。

dn: uid=user01,ou=People,…
objectClass: inetOrgPerson
objectClass: seciossOtpUser
uid: user01
cn: user01
sn: user01
userPassword: password01

3.2 SlinkOTP認証サーバの設定

“/var/www/conf/config.ini”を環境に合わせて変更して下さい。

[password]
storage = “LDAP”
uri = <LDAPサーバのURI>
binddn = <LDAPサーバに接続するユーザのDN>
bindpw = <LDAPサーバに接続するパスワード>
basedn = <ユーザを検索するベースDN>
keyfile = “/var/www/conf/auth_tkt.conf”

次に”/var/www/conf/auth_tkt.conf”に暗号化キーの設定を行います。SlinkOTPはワンタイムパスワードのPINとシークレットを暗号化してLDAPサーバに保存しますので、その際の暗号化にこのキーを使用します。

TKTAuthSecret <任意の文字列>

3.3 ソフトウェアトークン

ソフトウェアトークンは、iPhoneについてはApp Storeから、AndroidについてはGoogle Playから”SlinkOTP”を検索して、ダウンロードして下さい。
また、以下のソフトウェアトークンも利用可能です。

インストールしたらSlinkOTPを起動し、SeciossLinkユーザガイドの”4.5 ワンタイムパスワードのシークレットキー登録”の手順に従って、シークレットの登録を行って下さい。ただし、手順の中のWebサーバのURLは、今回構築したSlinkOTP認証サーバのURLとして下さい。

3.4 ハードウェアトークン

SlinkOTPが対応しているハードウェアトークンは、以下になります。

ハードウェアトークンのシークレットを登録するため、以下の形式のCSVファイルを作成します。

ユーザID>,<シークレット>,<ワンタイムパスワードの文字数>,<ワンタイムパスワードの生成間隔>

以下のコマンドを実行すると、LDAPにユーザのシークレットが登録されます。

# /opt/secioss/sbin/otpcmd.php add <CSVファイル>

ユーザのシークレットを削除する場合は、ユーザIDを記載したCSVファイルを作成し、以下のコマンドを実行して下さい。

# /opt/secioss/sbin/otpcmd.php del <CSVファイル>

4. ワンタイムパスワード認証

Webアプリケーションからワンタイムパスワード認証を行うには、以下の方法で認証サーバにユーザIDとワンタイムパスワードを送信して下さい。

レスポンスは、以下のXML形式になります。

<?xml version=”1.0″ encoding=”UTF-8″?>
< response>
<code>エラーコード</code>
<message>メッセージ</message>
< /response>

<?xml version=”1.0″ encoding=”UTF-8″?>
< response>
<code>エラーコード</code>
<message>メッセージ</message>
<id>ユーザID</id>
<sessid>セッションID</sessid>
< /response>

エラーコードは、以下の値を取ります。

以下はワンタイムパスワード認証のサンプルプログラムです。Basic認証のサンプルスプログラムから呼び出されます。

setMethod(HTTP_REQUEST_METHOD_POST);
    $req->addPostData('password', $_POST['password']);
    $res = $req->sendRequest();
    if (PEAR::isError($res) || $req->getResponseCode() != 200) {
        print("Authentication server returns error response
"); exit(1); } $xml = simplexml_load_string($req->getResponseBody()); $rc = intval($xml->code); if ($rc == 0) { // ==================== OTP省略 ==================== $code = NULL; $id = NULL; if (isset($_POST['remember']) && $_POST['remember']) { $url = "https://localhost/pub/psession.php?create=true&userid=$userid"; $timeout = 3; $postdata = "useragent=".urlencode($_SERVER['HTTP_USER_AGENT'])."&devicename=".urlencode($_POST['device_name']); $response = getContentsByUrl($url, $timeout, $postdata); // 登録成功であれば、クッキーを発行する if (preg_match('/([^<]*)<\/code>[^<]*([^<]*)<\/message>[^<]*([^<]*)<\/id>[^<]*([^<]*)<\/sessid>/', $response, $matches)) { $code = $matches[1]; $message = $matches[2]; $id = $matches[3]; $newsessid = $matches[4]; if ($newsessid) { setcookie("auth_otp", $newsessid, time()+36000, '/'); } } else { $message = $response; } print("
response: $response
code: $code
message: $message
id: $id
newsessid: $newsessid
"); } // ==================== OTP省略 ==================== setAuthenticated(array('localhost'), $sessid); print("ログインしました。"); exit(0); } else { $message = "ログインに失敗しました。
"; } } print('

User ID: '.$userid.'

Password:

Remember:

ワインタイムパスワードの停止

'.$message.'

'); ?>
  • ワンタイムパスワード認証(メール): motplogin.php
setMethod(HTTP_REQUEST_METHOD_POST);
    $req->addPostData('password', $_POST['password']);
    $res = $req->sendRequest();
    if (PEAR::isError($res) || $req->getResponseCode() != 200) {
        print("Authentication server returns error response
"); exit(1); } $xml = simplexml_load_string($req->getResponseBody()); $rc = intval($xml->code); if ($rc == 0) { // ==================== OTP省略 ==================== $code = NULL; $id = NULL; if (isset($_POST['remember']) && $_POST['remember']) { $url = "https://localhost/pub/psession.php?create=true&userid=$userid"; $timeout = 3; $postdata = "useragent=".urlencode($_SERVER['HTTP_USER_AGENT'])."&devicename=".urlencode($_POST['device_name']); $response = getContentsByUrl($url, $timeout, $postdata); // 登録成功であれば、クッキーを発行する if (preg_match('/([^<]*)<\/code>[^<]*([^<]*)<\/message>[^<]*([^<]*)<\/id>[^<]*([^<]*)<\/sessid>/', $response, $matches)) { $code = $matches[1]; $message = $matches[2]; $id = $matches[3]; $newsessid = $matches[4]; if ($newsessid) { setcookie("auth_otp", $newsessid, time()+36000, '/'); } } else { $message = $response; } print("
response: $response
code: $code
message: $message
id: $id
newsessid: $newsessid
"); } // ==================== OTP省略 ==================== setAuthenticated(array('localhost'), $sessid); print("ログインしました。"); exit(0); } else { $message = "ログインに失敗しました。
"; } } if (!isset($_SESSION['ismotpsent'])) { $req =& new HTTP_Request($send_url); $req->setMethod(HTTP_REQUEST_METHOD_POST); $req->addPostData('username', $userid); $res = $req->sendRequest(); if (PEAR::isError($res) || $req->getResponseCode() != 200) { print("Failed to send OTP mail
"); exit(1); } $json = json_decode($req->getResponseBody()); $rc = intval($json->code); if ($rc) { print("Failed to send OTP mail: ".strval($json->message)."
"); exit(1); } $_SESSION['ismotpsent'] = true; } print('

User ID: '.$userid.'

Password:

Remember:

ワインタイムパスワードの停止

'.$message.'

'); ?>