ホーム

認証のことを、何となく周辺の話題もからめて書いてみる(2)

前回のつづき。あいかわらず、それぞれの説明はすごく正確とは限りません。あらかじめ、すみません。

前回までは、主にユーザーIDとパスワードを使った認証とか、サービスと利用者の間のセッション管理の話とかをしました。その後、別のサービス間で認証を引き継ぐという話の予告までして終わりました。

認証を引き継ぐ、ということがもしもできれば、利用者にとっては、サービスごとにユーザーIDとパスワードをいちいち覚えておいてそれを打ち込まなくてはならない、という面倒がはぶけます。

そのための手段…では直接はありませんが、まずは、ユーザーIDとパスワードを、複数のサービスで共通にすることを考えてみます。こうすれば、少なくとも、ユーザーが覚えなくてはならない情報はひとまとまりにできますからね。

ユーザー情報を集約する

共通のユーザー情報データベースとしてすぐに思いつくのは、LDAP(えるだっぷ)やActive Directory(AD)でしょう。ADはMicrosoft社の製品名で、LDAPは仕様の名前です。ADはLDAPを実装している、とかそんな言い方ができます。LDAPを実装している製品は、このほかにも、オープンソースのOpenLDAPを含めいろいろあります。

LDAPのデータベースは、SQLなどを使って操作するようなものとは異なります。ですが、そこにひとつづつデータレコード(っていうのかな)を登録しておいて、あとでそれを自由に検索・取得できるという点は、まあ、普段思い浮かべる「データベース」と同じようなものかもしれません。

LDAPはユーザー情報のようなものを入れておくためだけに作られたものではありませんが、今いっている「ユーザー情報の集約」という文脈では、それを実現するのに適した仕組みです。データベースの中に、ユーザーID、パスワード(ほとんどの場合、ハッシュ化されたパスワード)、あとはユーザの名前やら、所属組織やら、補足的に必要な感じの情報をそれぞれ入れておきます。そしてそれをいろいろなサービスから参照するようにすれば、ユーザー情報の集約は一丁あがり、ということになりますね。

各サービスは、自分に向けてユーザーが入力したIDとパスワードを使って、あらかじめ知らされているLDAPサーバーに「このIDとパスワードで、本人に間違いありませんかねえ」といった感じの問い合わせをします。(ユーザーは、このLDAPとの「会話」が行われていることを知りませんし、別に知る必要はありません。)するとLDAPは「それでオッケー」とか「それは間違いだね」と(各サービスに向かって)返事をしますから、各サービスのほうはその返事を踏まえて、今度は自分がユーザーにログインを許すかどうかを決めます。LDAPからは「それでオッケー」とかいう返事以外に、必要ならば、そのユーザの名前とか所属とかの他にもデータベースに入っている情報まで同時にもらうことができますから、各サービスの側では、それを何かに役立ててもいいし、別に使わないでも構いません。

こういう仕組みにすることで、ユーザーは、同じLDAPに裏でつながっている限り、どのサービスを使う際にも、共通のユーザーIDとパスワードで認証されるようになるというわけです。

これで、ユーザーは、サービスごとに違うIDやパスワードを覚えておく必要がなくなりますから、人によっては、これで十分にハッピー、と言いたくなるところです。それでもあいかわらず、「同じだったとしても、そういう風にパスワードとか打ち込むのさえ面倒なんだよ!」という意見はあるでしょう。そのときはLDAPそれ自体が問題を解決してくれるわけではありませんね。ちぇっ。

ところで、ユーザーは自分のログイン用パスワードはいつでも自由に変更できるようになっているべきですが、LDAPを使っている場合でもそれができるでしょうか。各サービスごとに各々のユーザーIDとパスワードが管理されている(このことをローカルID管理っていうときがあります)場合は、ユーザーはそのサービスに向かって、何らかのパスワード変更の手続きをすればそれで済むでしょう。でも各サービスがLDAPを「参照」する役割しか持たされていない場合は、ユーザーの要求にこたえようにも、それができないということがありえます。こういう場合はたいてい、LDAP上に入っているユーザーパスワードをユーザー自身で変更できるような何らかの仕組みが、各サービスとは別に、どこかに準備されているものです。

上と同じような理由で、各サービス側では、ユーザーに関するすべての情報をLDAPに入れておくことをアテにできません。たとえば電子書籍を読むようなWebアプリケーションがあって、ユーザーが本を何ページまで読んだかを管理できるんだとします。サービス側ではその情報を、ユーザーごとの情報としてデータベースなどにとっておく必要がありますが、LDAPを更新するという権限があるとは限りませんし、LDAP側でそんなデータ項目をもっているとは限りませんし、そもそもLDAPはそんなに気ままにデータを書き換えるようには設計されていません。だから、サービスに固有の情報は、サービス側のデータベースで管理しておく必要があります。

ところで、RADIUS(らでぃうす)っていう、今説明したLDAPに仕組みが似ているものがありますので、少し触れておきます。RADIUSサーバーというものがあって、ユーザーからIDとパスワードを入力された各サービスが、この情報をつかって「このIDとパスワードの人って、大丈夫でしょうかねえ」という風に問い合わせると、その可否を返事してくれる、という仕組みです。LDAPといろいろな点で違いもあるのですが、そのひとつが、問い合わせの内容が、正確には「このIDとパスワードの人が、このサービスを使うのって、大丈夫でしょうかねえ」という形式になっている点のようです。 RADIUSサーバーは、LDAPと違って、各ユーザーが、それそれのサービスごとに、いちいち使えるか、使えないか、という情報を管理するという特徴があります。無線LANなどの認証に使われたりすることが多いものらしく、あまりWebアプリケーションの認証にRADIUSを使うという例は聞かないなあ。実は筆者はRADIUSをあまり触ったことがないのです。まあ、この段落は、なんかの参考まで。

(RADIUSとLDAPを比較するというのは実はちょっとナンセンスかもしれません。RADIUSが自分自身で使うデータベースとしてLDAPを使う、ということがあったりするわけなので、次元が違うんですね。)

LDAPとかRADIUSとかの話は、本筋とは逸れ気味だったかもしれません。でもまあ、脱線したり戻ったりしながら進めていくのが今回のやりかたなのです。

シングルサインオンの発想

さっきのLDAPの例で、ユーザーがログインするというだけのことなのに、ユーザー側とサービス側の二者だけでない、第三の登場人物が認証の仕組みに参入することがありうる、ということがわかりました。LDAPのときは、IDとパスワードのデータを管理するデータベースがそれでした。で、サービスとその「第三の登場人物」が、ユーザーのあずかり知らぬところで密かに「会話」することがある、ということもわかりました。ユーザーは、ふつうにサービスを使うかぎり、裏にLDAPが控えているのかどうかを知りえませんからね。

この様子を、前にも出したことがある、電話と受付係の例えに直してみましょう。大体こういうことが起こっている、というイメージを持つ助けになるでしょう。

ユーザーが最初にIDとパスワードを喋るのがだるい、っていう意見があるとして、こういう場合をどう改善できるでしょうか。これをなんとかするために、新たな登場人物「認証屋」ってのを仮に想定してみましょう。そして、以下のような展開が可能になればいいなあと思うんですが、どうでしょう。

とても不気味な会話が展開されています。まさにこのとおりのことが起こればとてもうまい話でしょうが、さすがにちょっと無理っぽいです。認証屋、どんなエスパーだよ。

でも、このアイデアは、認証屋がそれ自身のウェブサービスを開業していて、ユーザーとセッション確立済みなら、なんとか可能です。(セッションのことは、前の話で分かってくれているものとします。)つまりユーザーは、あるサービスにアクセスする前に、あらかじめ認証屋にログインしているということにするのです。

ユーザーは、認証屋にだけは、わざわざユーザーIDとパスワードを名乗ります。そうすればそれ以降楽ができると期待しているからです。あいかわらず認証屋のキャラが不気味なのは、まあそのほうがイメージしやすいかな、というそんだけの理由なので、あまり気にしないでください。

さて、認証屋にログイン済のユーザーは、あるお目当てのサービスを使うに先立って、下のような会話を認証屋としておきます。

チケットコードというものが、新たな小道具として登場しました。この呼び方は、今適当に考えました。シングルサインオンの実装によって、これをチケットとかトークンとかいろいろに呼びますが、別に本質は変わりません。で、ユーザーは、いよいよお目当てのABCサービスに電話します。

いかがでしょう。技術的に何が起こっているかという詳しい話はまず置いといて、この流れ、OKでしょうか? ユーザーの知らないところで、「認証屋」と「ABCサービス」が密かに通じている、というのが最大のキモです。

シングルサインオンとは、例えばこんな感じのことが起こることで実現します。でも、いろいろ疑問がわいてくるはずです。何より、ユーザーはABCサービスに「チケットコード」とかいうものを渡さなくては話が進まないみたいだ。これって、本当に面倒を省いていると言えるだろうか? パスワードを打ち込む手間と、チケットコードを覚えておいて打ち込む手間って、別に変らないんじゃないかな?

この疑問を解決するために、ウェブアプリケーションにおけるHTTPリダイレクト(または単にリダイレクト)のことと、URLのパラメータというものを簡単にわかっておく必要があると思いますので、下に説明します。

HTTPリダイレクト

Internet ExplorerとかMozilla Firefoxといったウェブブラウザは、ウェブから取得したデータを画面に表示しています。そのデータがどこから取得されたのかが、いわゆる「アドレス欄」というところに表示されています。アドレス欄に表示されている、「http://…」とか「https://…」とかで始まる文字列を、URLっていいます。(最近、一部のウェブブラウザでは、http:// という表示を省略しているときもあります。)ふつう、ブラウザがあるURLの内容を取得しようとすると、それに対応したデータがどしどしダウンロードされるものですが、それの代わりに、「この情報は、僕んとこじゃなくて、どこそこのURLに行って取得してね」といった、たらいまわし的な返事をよこすこともあります。

こいつがHTTPリダイレクト(または単にリダイレクト)というものです。はじめて聞いた、というかたも、実はしょっちゅう体験していることですよ。試しに、http://hdl.handle.net/2237/16265のリンク先にジャンプしてみてください。このリンクのもともとの飛び先は「hdl.handle.net」というホスト上にあるURLだったはずですが、いつのまにかアドレス欄は「http://ir.nul.nagoya-u.ac.jp/jspui/handle/2237/16265」に変わってしまっていませんか。リダイレクトが起こったとは、こういうときのことをいいます。ユーザーが、今からアクセスするURLが「実際のデータ」をよこしてくれるのか、または「リダイレクト」で別のURLに飛ばされてしまうのか、それはアクセスしてみるまでわかりません。リダイレクトをブラウザに指示するのは、サーバー側の仕事です。

リダイレクトが何のためにあるのかという理由は、いろいろあります。ひとつは(これが本来の理由でしょうが)、ある情報がどこか別のURLに引っ越してしまったときに、もとのURLにアクセスしてきた人を最新の場所に案内するためです。たとえば、さっきの http://hdl.handle.net/... で始まるURLは、ハンドルシステムというサービスを使うときに特徴的なものです。これは、実際の論文等を格納する機関リポジトリのホスト名やその他のパスが将来変化してしまった場合でも、リダイレクト元のURLさえ正しく覚えていれば必ずそこにたどり着けるようにという発想からつくられたサービスです。

シングルサインオンを実現させるために、このリダイレクトの仕組みが活用されます。これは今までの意味の「引っ越し」には対応しませんが、この「どっか別のURLに行ってらっしゃい」という機能がうまく活用できたのでしょうね。たとえば、ABCサービスならABCサービスにアクセスしたユーザーが、認証屋から発行されているはずのチケットコードをまだ持っていなかったとしたら、「あなたは、まず認証屋に行っといで!グッドバイ!」という感じのリダイレクトをABCサービスから食らって、ユーザーは知らない間に認証屋のログイン画面にたどりついている、という感じの動作が可能になります。ようこそムーンサイドへ!

URLパラメータ

もうひとつの技術的要素が、URLパラメータというやつです。URLの中に、ときどき「?」という記号があるのに気づくことがありませんか。その記号より右の部分が、いわゆるURLパラメータ(パラメータ、クエリーパラメータとも言われる)です。すごくよくある例としては、GoogleのWeb検索でおなじみのはずです。例えば今「パラメータ」でググってみたら、検索結果とともに、アドレス欄には https://www.google.co.jp/search?source=ig&rlz=&q=%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF&oq=&gs_l= と表示されました。(ここは環境によって異なります。)…/search までがURLの芯の部分で、残りはこの芯の部分に与えられた付加情報、まさにパラメータなわけです。このパラメータが何かによって、Webサーバー側は返してくれる情報を変えるかもしれませんし、変えないかもしれません。(Googleの場合は、もちろん「検索条件」を変えてくれますね。)

URLリダイレクトは、このパラメータ部分も含めてウェブブラウザにジャンプ先のURLを指定することができます。だから、さっきの例で「認証屋」が、「チケットコード**********を持って、ABCサービスに行くがよい」といった返事をユーザーに返すのは、技術的には「パラメータにチケットコードを持った、ABCサービスへのリダイレクト」なことがほとんどです。リダイレクトってのは、ユーザーが何も意識しない間に行われますから、実際のところ、ユーザーはチケットコードというものが「認証屋」と「ABCサービス」の間で媒介することさえ気づく必要がないわけですね。(ユーザーは、よく気を付けていれば、アドレス欄に、チケットコードがパラメータに入ったURLを目にするかも知れませんけどね。)

ここまで読んで、「認証屋が、チケットコードとかいうまどろっこしいものを持たせないでも、先方のサービスへのユーザーIDとパスワードをパラメータに混ぜて送り出してくれれば、いきなりログインできるから同じようなものじゃないかなあ」と思った人はいませんか。それは全く可能ですし、発想は悪くないと思います…が、このパラメータってのはブラウザのアクセス履歴に残ったりしますから、こんな仕組みにしたら、あとでパスワードバレ放題です。チケットコードってのは「認証屋」側ですぐ有効期限切れにしてしまうのが普通ですから、チケットコードはバレても大して問題がありません。でもパスワードみたいなのを直接URLパラメータに混ぜるのは、すごくよくないことだと思います。いいかげんに設計したシングルサインオンもどきのシステムには、ごくまれにそんな恐ろしい作りのものもある、らしい、のですが…

さて、いよいよこれから、シングルサインオンを実現するそれぞれの技術を挙げていくのですが…長くなってきたので、また回を改めるのがよさそう。

つづき

2012.11.5

クリエイティブ・コモンズ・ライセンス
この 作品 は クリエイティブ・コモンズ 表示 3.0 非移植 ライセンスの下に提供されています。