Morning Girl

Web API, Windows, C#, .NET, Dynamics 365/CRM etc..

PowerApps/CDS の WebAPI で OAuthブラウザログインが不要な接続を行う方法

先日開催した Office365 Graph APIに関する勉強会で Graph APIを使うためのアクセス許可のお話をしたんですが、その時に PowerApps・CDSでもこのアプリケーションアクセス許可が使えるよーと、ちらっとだけお話しました。

kageura.hatenadiary.jp

実はかなり前に Dynamics CRM版ではこのアプローチを紹介していたのですが、今回改めて PowerApps・CDSとして最新環境で書き直してみたものを紹介したいと思います。

アプリ認証のポイント

今回は以下のReferenceで紹介されている「アプリとして接続」を実施します。

アプリとして接続

このポイントはGraphAPI勉強会でもお話した「ClientCredentials 」で行う点と、この接続のための実行ユーザーを利用するという点にあります。

ClientCredentials つまるところアプリケーションのアクセス許可によるAPIの利用には、通常のOAuthプロセスで行われるユーザーログインの要求から、アクセス許可、アクセストークンの取得といったプロセスが存在しません。

そのため、明示的なアクセスユーザーが存在しない、というのが特徴なのですが、PowerApps CDSはそのアーキテクチャAPIの特性上、必ずアクセスユーザーというものが存在する前提で構成されています。

そのため、Azure ADアプリ登録までは基本的に同じプロセスなのですが、アプリとして接続するためのユーザーの作成と、そのユーザーとアプリを紐づける、という特殊な作業が発生します。

ここを抑えておくことが、アプロとしての接続を行う場合に重要なポイントとなります。

1. アプリの登録

何はともあれ、まずは Azure ADにアプリを登録しましょう。基本的な手順は今までの記事に書いてあるのと一緒です。

Azure Active Directory 管理センターに移動し、「アプリの登録」→「+新規登録」をクリック。

f:id:sugimomoto:20191014223210p:plain

任意のアプリケーション名を入力して、シングルテナントアプリケーションとして作成します。リダイレクトURIはローカルホストでかまいません。今回は特に使うシチュエーションがないためです。

f:id:sugimomoto:20191014223215p:plain

アプリを作成したら、クライアントIDを控えておきます。

f:id:sugimomoto:20191014223221p:plain

次に、「証明書とシークレット」の画面に移動して、クライアントシークレットを作成します。任意の名称と有効期間で登録し

f:id:sugimomoto:20191014223230p:plain

生成されたクライアントシークレットを同じように控えておきます。

f:id:sugimomoto:20191014223236p:plain

最後にAPIのアクセス許可を設定します。

f:id:sugimomoto:20191014223244p:plain

PowerApps・CDSと言いながら、アクセス許可的にはDynamics CRMを付与します。「PowerApps Runtime Service」というものもありますが、関係ありません。

f:id:sugimomoto:20191014223252p:plain

ここでちょっと注意なのですが、今回はClientCredentials で行うため、GraphAPIの文脈で行くとアプリケーションの許可になるのですが、PowerApps/CDSの性質上、それが使えません。そのため、「委任されたアクセス許可」を付与してあげます。

f:id:sugimomoto:20191014223259p:plain

2. PowerApps・CDS側 アプリ認証用ユーザーの作成

次にこのアプリ認証用のためだけのユーザーというものを作成します。このユーザーを先ほど作成したAzure ADアプリと紐づけることで、OAuth ClientCredentials 時に明示的なユーザーを指定しなくても、アクセスができるようになります。

まず、PowerAppsのCDS環境にアクセスし、設定アイコンから「詳細設定」の画面に移動します。

f:id:sugimomoto:20191014223306p:plain

私の環境が英語版で作ってしまったので英語ですが、日本語でもあまりかわらないです。設定一覧から「セキュリティ」に移動し

f:id:sugimomoto:20191014223313p:plain

ユーザーをクリックします。

f:id:sugimomoto:20191014223319p:plain

さて、ここでユーザーを作成するのですが、単純に「+新規」ボタンをクリックしてはいけません。

ここ「重要!」です。必ずビューの一覧から「アプリケーション ユーザー」を選択してください。

f:id:sugimomoto:20191014223324p:plain

「アプリケーション ユーザー」を選択した後に「+新規」をクリックすることで新規作成画面に移動できます。

f:id:sugimomoto:20191014223331p:plain

さらに、移動した後も気が抜けません。必ずフォームを「アプリケーション ユーザー」に切り替えてください。

f:id:sugimomoto:20191014223336p:plain

これで初めてアプリケーション ユーザーの作成を行うことができるようになります。

f:id:sugimomoto:20191014223342p:plain

この画面では、「UserName」「Applicaiton Id」「FullName」「PrimaryEmail」の4種類の項目を設定しますが、「Applicaiton Id」以外は自由に指定して大丈夫です。

「Applicaiton Id」のみ、先ほど作成したAzure ADアプリのClientIdを指定する必要があります。これを以下のように入力したら、保存をクリックします。

f:id:sugimomoto:20191014223348p:plain

保存した後、仕上げにこのユーザーに対してセキュリティロールを設定します。これがAPIアクセス時におけるアクセス許可範囲に相当します。今回はあまり気にせずSystemAdminを付与しました。

f:id:sugimomoto:20191014223354p:plain

3. AccessTokenを取得してみる

それでは設定した情報を使って、AccessTokenを取得してみます。私が使用したPostmanのコレクションも公開しておいたので、参考にしてみてください。

github.com

PostmanにCollectionとEnvironmentをインポート後、以下のように各環境変数を設定します。(AccessTokenは取得後)

f:id:sugimomoto:20191014223401p:plain

それでは実際に、生のHTTP Requestを確認します。

なお、今回試していてわかったのですが、どうやらまだAzureADV2のOAuth2エンドポイントには今回のアプローチが対応していないようでした。なので、以下のコードはV1で実施したものを記載しています。

Azure ADのAccessToken要求URLは「POST:https://login.microsoftonline.com/{{TenantId}}/oauth2/token」です。

ここにパラメータとして「grant_type=client_credentials」とともに、取得したClientId・ClientSecretを渡します。併せてResourceとして対象となるPowerApps・CDS環境のURLを渡すのがポイントですね。

AzureテナントIDとCDSテナント名は私が使っているものをそのまま記載していますので、適宜差し替えてRequestしてみてください。Postmanのコレクションでは環境変数にそのまま設定すればOKです。

POST /bb003c28-bf32-425d-b5cc-58dc86690470/oauth2/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=a98cea62-98f0-4b64-9d9d-b1265feb8ee5&client_secret=K2muHFy5VrBy1MW2_krbCB%3F%40vXXryLE%40&resource=https%3A%2F%2Forg61d4c5f1.api.crm.dynamics.com%2F

すると以下のようにAccessTokenを取得できます。

{
    "token_type": "Bearer",
    "expires_in": "3600",
    "ext_expires_in": "3600",
    "expires_on": "1571059373",
    "not_before": "1571055473",
    "resource": "https://org61d4c5f1.api.crm.dynamics.com/",
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImFQY3R3X29kdlJPb0VOZzNWb09sSWgydGlFcyIsImtpZCI6ImFQY3R3X29kdlJPb0VOZzNWb09sSWgydGlFcyJ9.eyJhdWQiOiJodHRwczovL29yZzYxZDRjNWYxLmFwaS5jcm0uZHluYW1pY3MuY29tLyIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0L2JiMDAzYzI4LWJmMzItNDI1ZC1iNWNjLTU4ZGM4NjY5MDQ3MC8iLCJpYXQiOjE1NzEwNTU0NzMsIm5iZiI6MTU3MTA1NTQ3MywiZXhwIjoxNTcxMDU5MzczLCJhaW8iOiI0MlZnWU9DOHZuQXpvNURwOWRrdWF3OEsyTG1yQUFBPSIsImFwcGlkIjoiYTk4Y2VhNjItOThmMC00YjY0LTlkOWQtYjEyNjVmZWI4ZWU1IiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvYmIwMDNjMjgtYmYzMi00MjVkLWI1Y2MtNThkYzg2NjkwNDcwLyIsIm9pZCI6IjQzMDQ2ZTI3LTM3MTUtNDE5NS05Yjk4LTE4MTVjYjkyYTFkMiIsInN1YiI6IjQzMDQ2ZTI3LTM3MTUtNDE5NS05Yjk4LTE4MTVjYjkyYTFkMiIsInRpZCI6ImJiMDAzYzI4LWJmMzItNDI1ZC1iNWNjLTU4ZGM4NjY5MDQ3MCIsInV0aSI6IlMwSG96RmVOUVVHRUszYml4NGRiQUEiLCJ2ZXIiOiIxLjAifQ.VEP12K8B3L2_GXMIKhdPPzndfh4iYn1WicJxNBnNIP8TAFTNZW7_39gtuGu4MMmYoa9yJnOXLmNp2TiW6mwxJRaALgmtl2FN-sb6xl01-j1lGOs-oVD_mPQwT7Ca_Y8Idql0Mj1OXIxqK93dEj4a-xNamRSF7iGzfdKh2uhi4CQVszg7iS_jU9zylp-gPi3aujJUuadTyDUlD_hevYfIJ0AHNuv9zotpvk5I7TjNfEwmEUQfnnYbIdr6KV13knw_0cAHzaQqjVpwMlww-_Y3dP7dFTGyu-rSW3c8HNm3tYVRc73tSY1_bExYrSFf8DWM47R7JY8mUph2zC_QNIkJfQ"
}

f:id:sugimomoto:20191014223426p:plain

これを使って、CDSのWeb APIにアクセスしてみると、以下のように取引先企業一覧が取得できました。

GET /api/data/v9.1/accounts HTTP/1.1
Host: org61d4c5f1.api.crm.dynamics.com
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc~~~~

f:id:sugimomoto:20191014223436p:plain

ちなみに、WhoAmI を実行すると、作成したアプリケーションユーザーで実行していることが確認できます。

f:id:sugimomoto:20191014223445p:plain

注意点

上記内容を見てもらえればわかると思いますが、ClientCredentialsを利用する以上、ClientIdとClientSecretが漏洩するとそのままPowerApps/CDSのWeb APIにアクセスができてしまいます。

通常のOAuthですとアプリに付与して公開とかあるかと思いますが、それとはまったく扱いが異なるものとなりますので、取り扱いにはご注意ください。

Microsoft Graph APIをテーマに 第25回 Office 365 勉強会を開催しました!

8月に福岡で開催された「Microsoft Graph 勉強会 in 福岡」に焚き付けられて、かなり久しぶりに主催で勉強会を開催しました!

f:id:sugimomoto:20191001093911p:plain

jpo365ug.connpass.com

初めは小規模でゆるーくできればいいかなーと思ったんですが、あれよあれよという間に申し込みだけで130名以上になってしまい、びっくりでした。

普段利用しているMicrosoftセミナールームが満杯で借りれなかったので、今回はWingarc1st 様に会場を貸していただいのですが、すごくロケーション・設備ともに充実していてよかったです!

f:id:sugimomoto:20191001094056j:plain

また、今回個人的初の試みとして勉強会の模様をYoutubeライブ配信しました!

最終的に個別セッションに動画を編集して公開しましたので、興味のある方は是非ご覧ください。

www.youtube.com

余談ですが動画撮影はGopro Hero7 Blackで実施。

ライブ配信はPC(OneMix2)と繋いで、Webカメラベースにして、Youtubeライブで配信しました。(GoPro標準のライブ配信Youtubeモバイルライブ配信になっていて、フォロワーが1000名必要なのでできませんでした)

音声はインライン入力していないので、ちょっと周りの拍手の音とかがうるさいかもです、、、。このあたりは今後要対策。

三脚はGoPro純正の3-Way。当日わたわたやっていたので、ちょっと水平調整が難しかったです・・・。

GoProをWebカメラとして利用するためのPCとの接続にはI-O DATAのUSB HDMI変換アダプター「GV-HUVC」を使用。これはあまり遅延もなくてよかった。ただ、意外と良いお値段・・・。

私のセッションについて

私のセッションでは、私自身がOffice365 Graph APIを使う過程で遭遇した躓きである、2種類のアクセス許可についてお話しました。

スライドはこちらで公開中。

speakerdeck.com

当日はデモベースで2種類のアクセス許可の実施方法を解説していますので、このあたりよくわかってないなーという方は動画も併せて是非参考にしてみてください。

Dynamics 365・CDSの認証部分についても触れていたりしますが、このあたりは一度もうちょっと深堀りしたいですね。

youtu.be

ちなみにこのセッションの詳細は以下のBlogでもまとめています。

Morning Girl:Office365 GraphAPI で認証アプローチ毎のアクセス範囲にハマった話 ユーザーの予定(Event)を横断的に取得したい! 

CData Software Japan Blog: CData Office365 Driverが「アプリケーションのアクセス許可(ClientCredentials)」に対応しました

Embulk を使って kintone から MySQL にデータをロード:CData JDBC kintone Driver

前回の記事では、シンプルなCSVファイルからMySQLへ、Embulkを使ってETL処理を実施しました。

今回は趣向を変えて、クラウドサービス kintone から MySQLにデータをロードしてみたいと思います。

続きを読む

Embulk を使ってCSVからMySQLにデータをロード:Windows 環境

最近 Embulk という良さげなETLツールを見つけました。

JDBC DriverもPluginで追加できるという、個人的に大ヒットなすぐれもの。基本的にはLinuxベースで動かす人が多そうですが、クロスプラットフォーム対応しているので Windows でも動かせます。

なので、とりあえずさくっと Windows で動かしてみました。

続きを読む

既存のGraphQLサービスからJSON形式のSchemaを生成する prisma/get-graphql-schema

何度かやってるんですが、毎回何でやったか忘れてしまうので書き残し。

GraphQLのスキーマを生成したい

GraphQLではスキーマが仕様上重要なポイントになっています。

f:id:sugimomoto:20190825154057p:plain

このスキーマを元に、クライアントやサーバーサイドのベースとなるソースコードを生成したりしますが、オープンなAPIにこれを取得するベーシックなアプローチは提供されていません。(ODataであれば、明示的にMetadataエンドポイントが提供されているのですが)

しかしながら、Github上でいくつかGraphQLサービスからスキーマを生成するプロジェクトがありましたので、その一つの使い方を紹介したいと思います。

続きを読む

Meetup #8 GraphQL Tokyo 2019 Summer のまとめにもならない参加メモ

はじめて GraphQL関係の勉強会「Meetup #8 GraphQL Tokyo 2019 Summer」に参加してきたました。

f:id:sugimomoto:20190816114035p:plain

www.meetup.com

セッションはオープンスペースという形式で参加者から募集したトピックと投票によって決定します。初めてだったんですが、事前にスライドの準備などはなく、ライブで進んでいくのが新鮮で面白かったですねー。

bliki-ja.github.io

全部で4セッション(2セッション X 前半後半)で、私は「マイクロサービスのサービス間通信で GraphQL を使うのは他の手法と比べてどうかの議論」と「SDL first or code-first ? https://www.prisma.io/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3」に参加しました。

以下、勉強会が終わったあとに、思い出すままに書いているざっくりしたメモの走り書きです。正直ついていくだけでめちゃくちゃハードだったので、まとまってもいないです。

続きを読む

PowerApps Portals で問い合わせページを作る ③ エンティティ・ページアクセス許可の設定

前回の記事では一覧画面を作成しました。

今回はその一覧画面に対して、ログインしたユーザーでアクセス範囲を規定する設定を、ポータルを通じて実現してみたいと思います。

docs.microsoft.com

続きを読む