<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Laravel &#8211; 株式会社カジトリ 技術ブログ</title>
	<atom:link href="https://develop.kajitori.co.jp/archives/tag/laravel/feed" rel="self" type="application/rss+xml" />
	<link>https://develop.kajitori.co.jp</link>
	<description>Officeアドイン、Laravel、Exmentなどの技術記事を記載します。</description>
	<lastBuildDate>Tue, 26 Jan 2021 14:14:36 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://develop.kajitori.co.jp/wp-content/uploads/2021/01/cropped-logo1-32x32.png</url>
	<title>Laravel &#8211; 株式会社カジトリ 技術ブログ</title>
	<link>https://develop.kajitori.co.jp</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>【Officeアドイン】OfficeアドインでSSOを有効化 実装編[Laravel]</title>
		<link>https://develop.kajitori.co.jp/archives/36</link>
					<comments>https://develop.kajitori.co.jp/archives/36#respond</comments>
		
		<dc:creator><![CDATA[hsatou]]></dc:creator>
		<pubDate>Tue, 28 May 2019 12:05:12 +0000</pubDate>
				<category><![CDATA[Officeアドイン]]></category>
		<category><![CDATA[Laravel]]></category>
		<guid isPermaLink="false">https://develop.kajitori.co.jp/?p=36</guid>

					<description><![CDATA[前回の記事の続きです。今回は、実際に実装して検証しました。 実装方針 MSのサイトに、node.jsとASP.NETのサンプルはすでにあるので、今回は別の言語で実装することにします。 今回は最近愛してやまない、PHPのL...]]></description>
										<content:encoded><![CDATA[<p>前回の記事の続きです。今回は、実際に実装して検証しました。</p>
<h1>実装方針</h1>
<p>MSのサイトに、<a href="https://docs.microsoft.com/ja-jp/office/dev/add-ins/develop/create-sso-office-add-ins-nodejs">node.js</a>と<a href="https://docs.microsoft.com/ja-jp/office/dev/add-ins/develop/create-sso-office-add-ins-aspnet">ASP.NET</a>のサンプルはすでにあるので、今回は別の言語で実装することにします。<br />
今回は最近愛してやまない、PHPの<b><span style="color: #ff0000">Laravel</span></b>で実装しました。Laravelサイコー。</p>
<p>なお、基本的には以下のドキュメントに記載の内容の後追いになります。こっちと自分の記事を読みながら検証するのがベスト。<br />
<a href="https://docs.microsoft.com/ja-jp/office/dev/add-ins/develop/sso-in-office-add-ins">https://docs.microsoft.com/ja-jp/office/dev/add-ins/develop/sso-in-office-add-ins</a></p>
<p><a href="https://docs.microsoft.com/ja-jp/office/dev/add-ins/develop/register-sso-add-in-aad-v2">https://docs.microsoft.com/ja-jp/office/dev/add-ins/develop/register-sso-add-in-aad-v2</a></p>
<p><span id="more-36"></span></p>
<h1>準備・設定</h1>
<h2>前提</h2>
<ul>
<li>
<p>今回構築するLaravelサイトの情報は以下になります。<br />
<a href="http://127.0.0.1:8000">http://127.0.0.1:8000</a><br />
※実際に公開する場合は、「127.0.0.1:8000」を修正してください<br />
※また、この記事を書き始めた当初、「localhost:9000」と思い、キャプチャを作成し始めてしまいました。そのため、キャプチャ内に「localhost:9000」があった場合、「127.0.0.1:8000」に修正をお願いします。  </p>
</li>
<li>
<p>Laravel5.6で構築しております。  </p>
</li>
</ul>
<h2>Office365インストール</h2>
<p>Office365のクライアント版を、Office365のサイトからインストールします。  </p>
<h2>Azure AD v2設定</h2>
<ul>
<li>
<p>以下のAzureポータルページにアクセスし、Office365のアカウントでサインインします。<br />
[<a href="https://go.microsoft.com/fwlink/?linkid=2083908">https://go.microsoft.com/fwlink/?linkid=2083908</a>]
</li>
<li>
<p>「アプリの登録」より、「新規登録」をクリックします。<br />
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190525213050-300x148.png" alt="" /></p>
</li>
<li>
<p>以下のように入力し、「登録」をクリックします。<br />
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190525213149-300x244.png" alt="" /></p>
</li>
<li>
<p>アプリケーション (クライアント) IDとディレクトリ (テナント) IDをコピーしておきます。（あとで使用します）<br />
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190525213414-300x116.png" alt="" /></p>
</li>
<li>
<p>「証明書とシークレット」をクリックし、「新しいクライアント シークレット」をクリックして、クライアントシークレットをコピーします。(こちらも後で使用します)<br />
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190525213534-300x118.png" alt="" /></p>
</li>
</ul>
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190525213643-300x197.png" alt="" />
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190525213747-300x37.png" alt="" />
<ul>
<li>「API の公開」→「設定」をクリックし、値に以下を入力します。<br />
api://(Webサイトのドメイン)/(先ほどコピしたアプリケーションID)<br />
例： api://127.0.0.1:8000/f4255842-2ac6-4b01-b8a6-aaaaaaaaaaaa  </li>
</ul>
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190525221840-300x138.png" alt="" />
<ul>
<li>「Scopeの追加」をクリックし、以下のように入力します。<br />
※スコープ名に「access_as_user」、同意できるのは誰ですかを「管理者とユーザー」と記入し、後は適当に  </li>
</ul>
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190525214443-300x281.png" alt="" />
<ul>
<li>「承認済みのクライアント アプリケーション」下の「クライアント アプリケーションの追加」をクリックし、<br />
「クライアントID」に以下の3つを入力し、「承認済みのスコープ」チェックを行い、「アプリケーションの追加」をクリックします。<br />
(Office系の設定値らしいです)<br />
d3590ed6-52b3-4102-aeff-aad2292ab01c<br />
57fb890c-0dab-4253-a5e0-7188c88b2bb4<br />
bc59ab01-8403-45c6-8796-ac3ef710b3e3  </li>
</ul>
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190525215007-300x261.png" alt="" />
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190525215115-300x133.png" alt="" />
<ul>
<li>「APIのアクセス許可」をクリックし、[Microsoft Graph] を選択してから [委任されたアクセス許可] を選択します。<br />
その後、以下にチェックを行い、「アクセス許可の更新」をクリックします。<br />
offline_access<br />
openid<br />
profile  </li>
</ul>
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190525215633-300x171.png" alt="" />
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190525215857-236x300.png" alt="" />
<p>最後に、「既定のディレクトリ に管理者の同意を与えます」をクリックします。  </p>
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190525220019-300x109.png" alt="" />
<p>以上で、Azure AD v2側の設定は完了です。  </p>
<h2>Laravel開発</h2>
<p>Laravelの開発を行っていきます。<br />
※composerをインストールしている前提です。composerの説明は割愛します。</p>
<ul>
<li>
<p>インストールするフォルダで、コマンドプロンプトなどで、以下のコマンドを実行します。<br />
実行後、officejs_sso_laravelフォルダにcdします。<br />
composer create-project &quot;laravel/laravel=5.6.*&quot; officejs_sso_laravel</p>
</li>
<li>
<p>以下のリポジトリより、phpファイルをダウンロードします。<br />
<a href="https://github.com/hirossyi73/office-js-sso-laravel">https://github.com/hirossyi73/office-js-sso-laravel</a></p>
</li>
</ul>
<p>該当ファイルを、Laravelディレクトリに上書きます。  </p>
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190525221236.png" alt="" />
<ul>
<li>.envファイルに、以下の値を記入します。<br />
CLIENT_ID=(コピーしたアプリケーションID)<br />
CLIENT_SECRET=&quot;(コピーしたクライアントシークレット。ダブルクオーテーションで囲むことを推奨)&quot;<br />
SCOPE=&quot;offline_access openid profile&quot;<br />
TENANT=(コピーしたテナントID)  </li>
</ul>
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190528091147-300x81.png" alt="" />
<ul>
<li>以下のコマンドを実行します。<br />
php artisan serve</li>
</ul>
<p>これで、以下のURLでサーバーが起動します。<br />
<a href="http://127.0.0.1:8000">http://127.0.0.1:8000</a>  </p>
<h2>Officeアドイン設定</h2>
<ul>
<li>githubより、マニフェストファイルをダウンロードします。  </li>
</ul>
<p><a href="https://github.com/hirossyi73/office-js-sso-laravel/blob/master/Office-Add-in-Laravel.xml">https://github.com/hirossyi73/office-js-sso-laravel/blob/master/Office-Add-in-Laravel.xml</a></p>
<ul>
<li>ダウンロードしたマニフェストファイルを開き、135行目以降のWebApplicationInfo以下の内容を修正します。</li>
</ul>
<pre><code>    &lt;WebApplicationInfo&gt;
      &lt;Id&gt;(アプリケーションID)&lt;/Id&gt;
      &lt;Resource&gt;api://(ドメイン)/(アプリケーションID)&lt;/Resource&gt;
        &lt;Scopes&gt;
            &lt;Scope&gt;openid&lt;/Scope&gt;
            &lt;Scope&gt;offline_access&lt;/Scope&gt;
            &lt;Scope&gt;profile&lt;/Scope&gt;
        &lt;/Scopes&gt;
    &lt;/WebApplicationInfo&gt;</code></pre>
<ul>
<li>
<p>マニフェストファイルを、Officeのセキュリティ設定で「カタログ URL」に設定したパスに配置します。  </p>
</li>
<li>
<p>PowerPointを開き、アドインを起動します。  </p>
</li>
</ul>
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190528143501-300x80.png" alt="" />
<ul>
<li>正常終了すると、このようにトークンが取得されます。</li>
</ul>
<img decoding="async" src="https://develop.kajitori.co.jp/wp-content/uploads/2021/01/20190528143602-300x223.png" alt="" />
<ul>
<li>このうち、
<ul>
<li>アドイントークン：OfficeのSSOから取得したトークンです。</li>
<li>ユーザー名：アドイントークンから取得したログインユーザー名です。</li>
<li>Eメール：アドイントークンから取得したメールアドレスです。</li>
<li>Graphアクセストークン：アドイントークンを使用し、PHP(Laravel)側で取得したMicrosoft Graphトークンです。もちろん、このトークンをMicrosoft Graphに使用すれば、情報を取得できます。  </li>
<li>Graphリフレッシュトークン：アドイントークンを使用し、PHP(Laravel)側で取得したMicrosoft Graphのリフレッシュトークンです。  </li>
</ul>
</li>
</ul>
<h1>解説</h1>
<p>ソース単位でご説明します。</p>
<h3>アドイントークン取得</h3>
<p>以下の内容で、アドイントークンを取得しています。</p>
<pre><code class="language-javascript">//  app.js
(function(){
    // 初期化処理
    Office.onReady(function(info) {
        if(!Office.context.auth.getAccessTokenAsync){
            log(&#039;Office.context.auth.getAccessTokenAsync not supported&#039;);
            return;
        }

        // 認証実行
        Office.context.auth.getAccessTokenAsync(function (result) {
            if (result.status === &quot;succeeded&quot;) {
                // Use this token to call Web API
                var ssoToken = result.value;
                $(&#039;#addin_token&#039;).val(ssoToken);

                // decode user info
                var decoded = jwt_decode(ssoToken);

                $(&#039;#username&#039;).val(decoded.name);
                $(&#039;#email&#039;).val(decoded.preferred_username);

                getGraphToken(ssoToken);
            } else {
                if (result.error.code === 13003) {
                    // SSO is not supported for domain user accounts, only
                    // work or school (Office 365) or Microsoft Account IDs.
                } else {
                    // Handle error
                }

                log(&#039;error &#039; + result.error.code);
            }
        });
    });
})();</code></pre>
<p>ポイントは「Office.context.auth.getAccessTokenAsync(function (result) {」で、この関数で、PowerPointのアプリケーションからSSOで、アドインのトークンを取得しています。<br />
トークンはJWT形式なので、「//decode user info」の部分で内容を解析し、名前とメールアドレスを取得しています。  </p>
<h3>Microsoft Graphトークン取得</h3>
<p>以下の内容で、Microsoft Graphトークンを取得しています。</p>
<pre><code class="language-javascript">//  app.js

/**
 * Microsoft Graphのトークンをサーバーサイドから取得
 * @param string apptoken アドイントークン
 */
function getGraphToken(apptoken){
    var CSRF_TOKEN = $(&#039;meta[name=&quot;csrf-token&quot;]&#039;).attr(&#039;content&#039;);

    $.ajax({
        url:&#039;./graphtoken&#039;,
        type:&#039;POST&#039;,
        data:{
            &#039;apptoken&#039;:apptoken,
            &#039;_token&#039; : CSRF_TOKEN,
        }
    })
    // Ajaxリクエストが成功した時発動
    .done(function(data){
        $(&#039;#graph_token&#039;).val(data.access_token);
        $(&#039;#graph_refresh_token&#039;).val(data.refresh_token);
    })
    // Ajaxリクエストが失敗した時発動
    .fail(function(data){
        log(&#039;Graph token error : &#039; + JSON.stringify(data));
    })
    // Ajaxリクエストが成功・失敗どちらでも発動
    .always(function(data){
    });
}
</code></pre>
<pre><code class="language-php">// IndexController.php
    /**
     * Graphのトークン取得
     *
     * @return void
     */
    public function graphtoken(){
        $apptoken = request()-&gt;get(&#039;apptoken&#039;);

        // ホントはここで検証を行う

        // Graphのアクセストークンを代理フローで取得
        // https://docs.microsoft.com/ja-jp/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow
        $client = new \GuzzleHttp\Client;

        $res = $client-&gt;request(
            &#039;POST&#039;,
            &#039;https://login.microsoftonline.com/common/oauth2/v2.0/token&#039;,
            [
                &#039;form_params&#039; =&gt; [
                    &#039;grant_type&#039; =&gt; &#039;urn:ietf:params:oauth:grant-type:jwt-bearer&#039;,
                    &#039;client_id&#039; =&gt; env(&#039;CLIENT_ID&#039;),
                    &#039;client_secret&#039; =&gt; env(&#039;CLIENT_SECRET&#039;),
                    &#039;assertion&#039; =&gt; $apptoken,
                    &#039;scope&#039; =&gt; env(&#039;SCOPE&#039;),
                    &#039;requested_token_use&#039; =&gt; &#039;on_behalf_of&#039;,
                ]
            ]
        );

        $list = json_decode($res-&gt;getBody()-&gt;getContents(), true);
        return $list;
    }</code></pre>
<p>検証をサボってますが、本番環境では検証、ちゃんとやってくださいね。<br />
この内容によって、代理フローを使用し、Microsoft Graphトークンを取得するわけです。</p>
<h1>まとめ</h1>
<p>長くなってしまいましたが、以上でSSOを使用したサンプルは完了します。<br />
今後実装を検討される方は、是非参考にしてみてください！</p>
]]></content:encoded>
					
					<wfw:commentRss>https://develop.kajitori.co.jp/archives/36/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
