Office 365 SharePoint Online のプログラミングによる認証 (Authentication)


2013/07 追記 : SharePoint 2013 Online 以降では、「Native Application で SharePoint Online に Login して REST サービスなどを呼び出すプログラミング」に記載した方法が使用可能です。(OAuth を使用します。)

こんにちは。日本のゴールデン ウィークに浸り、今日、久々の出社です。

さて、Office 365 Public Beta をお使いの開発者の方も多いと思いますが、Office 365 の SharePoint Online に接続するクライアント アプリケーションを作成したことがある方は、ここで記載する罠に、間違いなく、はまったことでしょう。(私も、その中の 1 人です . . .)
作っていただくとわかりますが、今までのように NetworkCredential が使えません。(BPOS の頃の SharePoint Online では、Basic 認証が使用されていました。) Fiddler などでプロトコルを調べ、あの手、この手と奮闘し、最終的に裏技に行き着いた開発者の方も多かったことでしょう。

さて、このたび、MSDN で、この Office 365 の SharePoint Online の認証方法について正式にドキュメントが提供されました!

[MSDN] Remote Authentication in SharePoint Online Using Claims-Based Authentication

http://msdn.microsoft.com/en-us/library/hh147177.aspx

さらに、この中で紹介している手法を実現したサンプル コードも提供されていますので、是非動作を確認してみてください。SharePoint Online のサイトに接続し、サイト名をコンソールに表示するという簡単なサンプルです。

[MSDN Code Gallery] Remote Authentication in SharePoint Online Using the Client Object Model

http://code.msdn.microsoft.com/Remote-Authentication-in-b7b6f43c

なお、サンプル コードを動作させる際は、接続先の SharePoint Online の URL を引数に与える必要がありますので、Visual Studio のプロジェクトのプロパティで [デバッグ] タブを開き、[コマンドライン引数] を設定しておくと良いでしょう。(URL として https を使用し、http は使用しないでください。)
また、企業内などでプロキシ サーバーを使用している際には、下記の通り、プロキシ設定もおこなっておくよう、コードを追記しておきましょう。

. . .

static void Main(string[] args)
{
    // Added below . . .  (Using Proxy)
    IWebProxy proxyObject = new WebProxy("proxy.xxx.microsoft.com:8080", true);
    WebRequest.DefaultWebProxy = proxyObject;

    if (args.Length < 1) { Console.WriteLine("SP_Ctx <url>"); return; }

    . . .

}

さて、これまでハマったことがない幸運な方のために、Office 365 の SharePoint Online の認証において、何が問題となり、このサンプル コードによって何を解決しているのか、簡単に紹介しておきましょう。(ハマりそうな順番に記載してみます . . .)

  • まず、Office 365 の SharePoint Online では、Basic 認証や、フォーム認証などは使用していません。SharePoint Online を使用すると、既定で、Microsoft Online Services の認証サービスと連携した、Passive 型のクレーム ベース (Claim Base) 認証が使用されています。
  • このため、NetworkCredential などを使った接続や、Authentication.asmx を使ったフォーム認証も不可能です。(そもそも、SharePoint Online では、Authentication.asmx は使用できないようになっています。これは、BPOS の頃も同様です。)
    同様に、SharePoint 2010 が提供するクライアント用のライブラリ (Client OM については、こちら を参照) でも、準備されている既定の方法では使用できません。(例えば、SharePoint Server 2010 の Client OM においても、フォーム ベース認証では、内部で、Authentication.asmx を呼び出しています。)
  • 上述の Passive によるクレーム ベースの処理では、接続時にアクセス拒否のレスポンスが返ると共に、最終的に、(HTTP の) レスポンス ヘッダーによって、Microsoft Online Services の認証サーバーのサイトにリダイレクトされます。(いくつかの URL を経てリダイレクトがおこなわれます。)
    そして、Microsoft Online Services での認証後、最終的に、FedAuth というクッキー (Cookie) の値を書き込み、SharePoint Online のサイトに戻されます。SharePoint Online では、このクッキーの値によって、認証されたかどうか判断します。
  • そこで、.NET に慣れたプログラマーの方であれば、以下のように考えることでしょう。(実際、SharePoint Workspace Mobile 2010 などで Office 365 のサイトに接続すると、いったん、ブラウザが表示されます。)
    • リダイレクトなどの細かな処理は、WebBrowser コントロールに任せる。(無論、全部をコードで処理すると大変ですから)
    • イベントを取得し、認証完了後に、上記のクッキー (FedAuth) の値を取得し、このクッキーの値を使って HWR (HttpWebRequest) などを使用したプログラミング (こちら を参照) をおこなう。
  • しかし、上記のプログラム コードには問題あります。FedAuth は、HttpOnly Cookie と呼ばれるクッキーで、JavaScript や .NET (C#, Visual Basic) のコードから、直接、WebBrowser コントロールの中にある この Cookie へのアクセスは禁止されているためです。このため、単純に .NET のコードを使って FedAuth Cookie を取得することはできません。(Cross-Site Scripting による別サイトからの盗難を防止するため、厳重に守られています。)
  • これを克服するため、Internet Explorer (IE) が内部で使用している wininet.dll の InternetGetCookieEx 関数を呼び出します。つまり、.NET のプログラマーの方は、PInvoke することになります。

こうしたノウハウが、上記のサンプル コード内で実装されています。
上記の手順をすべてコーディングすると、ちょっと大変ですね。上記のサンプル コードでは ClaimClientContext クラスとしてきれいにモジュール化されていますので、是非このコードを活用してみてください。(あくまでも「サンプル」ですから、自己責任でメンテナンスしてくださいね。)

(またアップデートがあれば記載します . . .)

追記 : SharePoint Online (Office 365) のブラウザーを使用しない認証については、WS-Trust が使用できます。コメント (下記) を参照してください。(こちらの投稿 にサンプル コードを置きました。AD FS 連携のケースについては、「AD FS フェデレーションを処理する Client Programming (Office 365 編)」に掲載しました。)

追記 : SharePoint 2013 Online からは、プログラム用に、/_vti_bin/idcrl.svc を使用して、ブラウザーを使用せずに FedAuth クッキーの取得が可能です。(BPOSIDCRL という独自の方式を使用します。)
これは、SharePoint 2013 の .NET CSOM (Microsoft.SharePoint.Client.SharePointOnlineCredentials) などで使用されています。

 

Comments (5)

  1. 今日は大変興味深く拝見させていただきました。!

    Office 365 SharePoint OnlineでNetworkCredential が使えないのはとても残念です。

    紹介されているサンプルを使用してみたのですが、

    ログインダイアログが表示されるんですね。

    Office 365 SharePoint Onlineに対して、ブラウザを使用せずに

    リモートからライブラリ内のファイルを操作するアプリを検討しているのですが、

    実現は可能でしょうか?

    認証さえできれば、Webサービスでできると思うのですが・・・

    対象は以下を考えています。

    Linux+Java

    Windows+C#

    回答頂けると、とても助かります。

    以上、よろしくお願い致します。

  2. コメント、ありがとうございます。

    ブラウザーを出さずに認証させる件ですが、申し訳ありません、現状は、”事実上、不可能” な状況です。

    同じクレーム ベースでも、ACS などでは API などからの認証を考慮した方法なども提供されていますが、現状の Microsoft Online Services における SharePoint Online では、ブラウザーにおける、クッキーや、リダイレクト、フォームなどのさまざまな機能 (例えば、Location ヘッダーや、JavaScript による Form の Submit など) を前提とした、Passive な方式しか入口が提供されていないため、こうした処理をプログラミングですべて対処させようすると、最終的に、最終的にブラウザーそのものをプログラミングする結果となってしまうためです。(このため、Windows Phone 7.5 の SharePoint Workspace Mobile や、Office クライアントを開いた際など、Office 365 と接続可能な周辺機能では、すべて、初回の Office 365 SharePoint Online のログイン時に、ブラウザーの画面が表示されるようになっております。)

    これは、Linux 上で組む場合も同様な結果になるかと思われます。

    ご指摘の通り、認証さえできれば、あとは REST API など自由に接続できるのですが、窮屈な状況で申し訳ありません。(同様のフィードバックは多数頂いております。特に、Windows Phone では、現在、Silverlight による実装が必要なため、P/Invoke などもおこなうことができません。)

    まだ、いつ、どのような、といった内容はお話できませんが、本件に絡むアップデートがありましたら、すぐにこのブログでも紹介 (ご報告) させていただきます。

  3. 丁寧な回答ありがとうございます。

    アップデートの紹介を楽しみにしています!

  4. active 認証 (ブラウザーを使用しない認証) につきまして、追加で情報いただきましたので掲載致します。

    MSDN のドキュメントには掲載されておりませんが、SAML 1.1 のトークンを返す STS (login.microsoftonline.com/extSTS.srf) が立っており、この STS を使用して SAML トークンを取得することで、Office 365 (SharePoint Online) のサイトに認証を要求 (最終的に、上記と同じ FedAuth を取得) することができるそうです。

    こちらの投稿 にサンプル コードを置いていますのでご参照ください。(追加の回答となり、すみません。最終的に、active 認証は可能です。)

    2012/10/31 追記 : Windows 8 Store App から Office 365 に認証をおこなうコードについては、こちら (Omar Venado's Blog) に掲載されていますので、参考にしてください。(Office 365 Preview 版です。)

  5. SharePoint newbie says:

    こんにちは、Cookieの読み込みについて聞きたいことがあります。

    Office365の無料体験版(portal.microsoftonline.com/…/default.aspx)を使っています。SharePointにリストを作成して、そのリスト(newbie.sharepoint.com/…/AllItems.aspx)のdomain URLでFedAuth cookieを読み込もうとしたら失敗しました。

    このリストURLをIEのTrusted siteに登録するとCookieを読み込めるですけど、その原因がわかりません。

    この記事の中で「URL として https を使用し、http は使用しないでください」と書いてありますがhttpでは何がダメですか?なぜこのやり方で失敗するのでしょうか?どうすれば成功するのでしょうか?

Skip to main content