Biz メール シングルサインオン 連 携 サービス IF 仕 様 書 第 1.0 版 NTT コミュニケーションズ 株 式 会 社 i
変 更 履 歴 Biz メール SSO 連 携 サービス IF 仕 様 書 変 更 年 月 変 更 内 容 1 2012-04-05 新 規 作 成 ii
目 次 1 はじめに...4 1.1 本 書 の 目 的...4 2 SSO(シングルサインオン)...5 2.1 機 能 概 要...5 2.2 SSO リダイレクト 詳 細...5 2.3 認 証 用 生 成 値 の 生 成 方 法...6 2.4 ドメイン 追 加 時 の 手 順...7 2.5 SSO エラー 発 生 時 の 切 り 分 け 手 順...7 2.6 遷 移 先 URL...7 2.7 SSO 用 JSP のサンプル...7 iii
1 はじめに 1.1 本 書 の 目 的 本 書 は Biz メールサービスへのシングルサインオン( 以 下 SSO)を 実 現 するための 手 順 について 記 述 する 4
2 SSO(シングルサインオン) 2.1 機 能 概 要 通 常 Biz メールのメールクライアントを 利 用 する 場 合 ユーザは Biz メールサーバ への 認 証 行 為 が 必 要 となるが ユーザのメールアドレスが 連 携 システムで 認 証 された 場 合 は Biz メールサーバに 対 して 内 部 的 に 認 証 処 理 を 行 うことにより ユーザに Biz メー ルサーバへの 認 証 行 為 を 行 わせることなく Biz メールのメールクライアントを 利 用 させ ることができる SSO 機 能 で 認 証 させるにはBiz メール 側 で 認 証 するために 必 要 なパラメータの 生 成 を 行 い Biz メールに 対 してリダイレクトする 必 要 がある 連 携 システムから Biz メール へ SSO する 際 の 処 理 遷 移 について 図 1に 示 す User 連 携 システム Biz メール Biz メール 起 動 SSO リダイレクトURL 生 成 SSO リダイレクト 先 URL を リターン SSO 処 理 SSO 認 証 完 了 ログイン 後 操 作 図 1 : SSO 処 理 遷 移 2.2では 生 成 するパラメータおよびリダイレクト 方 法 について 記 述 する 2.2 SSO リダイレクト 詳 細 リダイレクト 先 の URL のフォーマットは 以 下 のフォーマットとなる http://<biz メールホスト 名 >/service/preauth? account={account-identifier& by={by-value& timestamp={time& expires={expires& preauth={computed-preauth redirecturl={redirection-url 5
表 1 : リダイレクト URL パラメータ 一 覧 # パラメータ 必 須 内 容 1 account- identifier メールアドレス 2 by-value name 固 定 3 time 現 在 時 刻 のミリ 秒 1 4 expires 0 固 定 5 computed-preauth 認 証 用 生 成 値 (2.3 認 証 用 生 成 値 の 生 成 方 法 ) 6 redirection-url 遷 移 先 URL(2.36 遷 移 先 URL) 1:シングルサインオン 処 理 を 行 うサーバのシステム 時 刻 との 差 が 前 後 5 分 以 内 に 収 ま っていなければエラーとなる 2.3 認 証 用 生 成 値 の 生 成 方 法 認 証 用 生 成 値 を 生 成 する 手 順 は 以 下 のとおり 1 account by expires timestamp の 値 を で 連 結 した 文 字 列 を 生 成 2 連 結 した 文 字 列 を SHA-1 HMAC で PreAuthKey( 後 述 )を 使 用 し 暗 号 化 し 16 進 数 文 字 列 に 変 換 2.3.1 文 字 列 の 連 結 表 2のパラメータの 値 より 文 字 列 を 連 結 する 表 2 : 連 結 文 字 列 の 設 定 値 # パラメータ 値 1 account john.doe@domain.com 2 by name 3 expires 0 4 timestamp 1135280708088 [ 連 結 文 字 列 の 例 ] john.doe@domain.com name 0 1135280708088 2.3.2 SHA-1 HMAC で 暗 号 化 し 16 進 数 文 字 列 に 変 換 2.3.1 で 連 結 した 文 字 列 を 元 に 弊 社 より 別 途 提 示 させていただく PreAuthKey を 使 用 し 暗 号 化 処 理 を 行 う 連 結 した 文 字 列 を PreAuthKey で 暗 号 化 し 16 進 数 の 文 字 列 に 変 換 する hmac("john.doe@domain.com name 0 1135280708088", "6b7ead4bd421836e8cf0379cd6c1a04acc127abd07c8ee4b61023e19220e929c"); 認 証 用 生 成 値 : b248f6cfd027edi45c5h69f8490125k04772f844 PreAuthKey 及 び 認 証 用 生 成 値 はサンプル 生 成 した 認 証 用 生 成 値 を 元 に2.2のフォーマットに 従 い リダイレクトすることでシン グルサインオンが 可 能 となる 6
2.4 ドメイン 追 加 時 の 手 順 PreAuthKey はドメイン 単 位 で 必 要 となるため 新 たなドメインを 追 加 する 場 合 は 新 ドメインでシングルサインオン 連 携 サービスの 申 し 込 みをする 必 要 がある 2.5 SSO エラー 発 生 時 の 切 り 分 け 手 順 2.6 遷 移 先 URL SSO 成 功 後 の 遷 移 先 画 面 はパラメータの redirecturl で 指 定 する 指 定 できる 値 について 表 3 に 示 す 表 3 : 遷 移 先 URL の 設 定 # パラメータ SSO 成 功 後 の 遷 移 先 画 面 1 省 略 時 アドバンスト 版 2 /webmail/h/ 標 準 版 3 /webmail/m/ スマートフォン 画 面 2.7 SSO 用 JSP のサンプル <%@ page contenttype="text/html; charset=ms932" %> <%@ page import="java.security.invalidkeyexception" %> <%@ page import="java.security.nosuchalgorithmexception" %> <%@ page import="java.security.securerandom" %> <%@ page import="java.util.hashmap" %> <%@ page import="java.util.map" %> <%@ page import="java.util.iterator" %> <%@ page import="java.util.treeset" %> <%@ page import="javax.crypto.mac" %> <%@ page import="javax.crypto.secretkey" %> <%! // preauth 定 義 開 始 // preauthkey( 以 下 はサンプル)を 指 定 する public static final String DOMAIN_KEY = "6b7ead4bd421836e8cf0379cd6c1a04acc127abd07c8ee4b61023e19220e929c "; public static String generateredirect(httpservletrequest request, String name) { HashMap params = new HashMap(); String ts = System.currentTimeMillis()+""; params.put("account", name); params.put("by", "name"); // needs to be part of hmac params.put("timestamp", ts); params.put("expires", "0"); // means use the default String preauth = computepreauth(params, DOMAIN_KEY); + returnrequest.getscheme()+"://"+request.getservername()+":"+request.getserverport()+"/service/preauth/?" "account="+name+ "&by=name"+ "×tamp="+ts+ "&expires=0"+ 7
"&preauth="+preauth; public static String computepreauth(map params, String key) { TreeSet names = new TreeSet(params.keySet()); StringBuffer sb = new StringBuffer(); for (Iterator it=names.iterator(); it.hasnext();) { if (sb.length() > 0) sb.append(' '); sb.append(params.get(it.next())); return gethmac(sb.tostring(), key.getbytes()); private static String gethmac(string data, byte[] key) { try { ByteKey bk = new ByteKey(key); Mac mac = Mac.getInstance("HmacSHA1"); mac.init(bk); return tohex(mac.dofinal(data.getbytes())); catch (NoSuchAlgorithmException e) { throw new RuntimeException("fatal error", e); catch (InvalidKeyException e) { throw new RuntimeException("fatal error", e); static class ByteKey implements SecretKey { private byte[] mkey; ByteKey(byte[] key) { mkey = (byte[]) key.clone();; public byte[] getencoded() { return mkey; public String getalgorithm() { return "HmacSHA1"; public String getformat() { return "RAW"; public static String tohex(byte[] data) { StringBuilder sb = new StringBuilder(data.length * 2); for (int i=0; i<data.length; i++ ) { sb.append(hex[(data[i] & 0xf0) >>> 4]); sb.append(hex[data[i] & 0x0f] ); return sb.tostring(); private static final char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'; // preauth 定 義 終 了 %> <% // Preauth メインロジック 開 始 try { String account = request.getparameter("account"); //---------------------------------------------------- // 他 システム 認 証 (POP など) //---------------------------------------------------- //---------------------------------------------------- // 他 システム 認 証 が OK の 場 合 は 8
// Biz メールサーバ 認 証 OK として preauth にリダイレクトする //---------------------------------------------------- String redirect = generateredirect(request, account); response.sendredirect(redirect); catch (Exception ex) { // 例 外 が 発 生 した 場 合 の 処 理 finally { // finally 処 理 // Preauth メインロジック 終 了 %> 9