O365でアプリケーション登録→APIアクセスしようとして
はまったわー
やりたいこと
- Office365を契約
- AzureADにアプリケーションを登録
- アプリケーションのアプリケーションID,秘密鍵を使ってアクセストークンを取得
- プログラムからアクセス
1. Office365を契約,AzureADにサインアップ
O365はE5を契約。
サインアップ後、裏でデプロイされたAzureADにアプリケーション登録しようとAzureクラシックポータルにアクセスするが、AzureADサインアップ時にエラーになる。
パターン1. サインアップでエラー
電話による認証、クレジットカードによる認証を進めたところ、サインアップでエラーになった。原因不明。
パターン2. 電話による本人確認でエラー
そんな事を繰り返していたら、電話認証で番号を入れたタイミングで「アカウントを確認できませんでした。サポートにお問い合わせください。 」というエラーが出るようになった。想像だが、同じ電話番号で何度も認証していたらこのエラーが出るのではないか。証拠として、適当な電話番号を入力したときはエラーが出ずに認証コード入力画面になった(その番号の人、すいません)
2. AzureADにアプリケーションを登録
AzureADにアプリケーション登録をする手順は3つあるようです。
- Azureクラシックポータルから登録
- Azureポータル(以前、プレビューと言われていたものから登録)
- Office 365 ユーザーとエンタープライズ ユーザーのサインインを可能にする – Microsoft ID プラットフォームから登録
1.は今までのセオリーだったもの。
2について。最近、AzureクラシックポータルからAzureポータルへの機能移転が進んでおり、旧来Azureクラシックポータルでやっていたアプリ登録もAzureポータルから出来るようになったようです。
左ペインのAzure Active directory -> アプリの登録 -> +追加からアプリを登録。適切な権限を付与してキーを作成する。ただし、この機能はプレビュー版なので動作が怪しい可能性があります。(今回は大丈夫だったぽい)
んで、3はいったいなんなの?という話ですが、どうやらMSは商用のOffice365も私用のOutlook.comも同じコードで開発できるよう、RESTのエンドポイントを統一し、組織アカウントでログインすれば商用O365を、個人アカウントでログインすれば、Outlook.com側を触るようなAPIを実装しているらしい。
v2.0 endpoint の OAuth を使った Client 開発 (Azure AD と MSA への対応) – Tsmatz
そのアプリ登録のフロントエンドが、上記リンクの「Microsoft ID プラットフォーム」というわけ。ここからアプリ登録すると、裏側の仕組みとしてはログインした組織アカウントのAzureADにアプリ登録されるだけ。しかも、現状では「Microsoft ID プラットフォーム」画面からはGraph API関連の権限しか付与できず、outlook APIの権限はコントロールできない様子。
将来的に、製品個別のAPIがGraph APIに統一されるのを見越せば、本命は「Microsoft ID プラットフォーム」なんだろうけど、現時点では特別にこれを使う理由はなさそうです。
認証API v1.0 と v2.0について
よくわかってないです。
- API エンドポイントが違う
- 使える機能が違う(ほんと?)
- v2.0 認証エンドポイント プレビューを使用した Office 365 API と Outlook.com API の認証 | MSDN
- 現時点では、メール、連絡先、予定表のみ
- GraphAPIだから、それだけしか使えないんじゃないの?
- Outlook API v1.0 と v2.0とは関係ない(ほんと?)
- なので、認証はv2.0を使うのがよさそう?
3. アプリケーションのアプリケーションID,秘密鍵を使ってアクセストークン(認証トークン)を取得
認証API v1.0での認証手順
- 以下のフォーマットで認証エンドポイントにアクセス
- https://login.microsoftonline.com/common/oauth2/authorize?response_type=code&client_id=[クライアントID]&resource=https%3a%2f%2foutlook.office365.com%2f&redirect_uri={リダイレクトURL}
- このようなレスポンスがあれば成功
- https://localhost/myapp?code=[認証トークン]&session_state=[セッション情報]]
当初、リダイレクトURLとホームページURLを不一致としていたら、認証コードが取れなくてめちゃくちゃハマった。リダイレクトURLを"https://portal.office.com“に設定していたせいかもしれないが…。以下のようなレスポンスしか返ってこなかった。
ひとまずマニュアル通り、https://localhost/myapp宛にリダイレクトする設定にした。ここでもハマって、どこかのサンプルでhttp://localhost/myappをリダイレクト先に指定していたのでコピペしたら、実はhttpsでないと全て無効なURLとなってしまうらしいことが分かった。どこにも書いてないんですが…。
認証API v2.0での認証手順
Get Started with the Outlook REST APIs – Outlook Dev Center
https://login.microsoftonline.com/common/oauth2/v2.0/authorize
- 以下のフォーマットで認証エンドポイントにアクセス
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=[クライアントID]&redirect_uri=[リダイレクトURL]]p&response_type=code&scope=[スコープ]]
スコープはこんな感じで指定する↓
v2.0 認証エンドポイント プレビューを使用した Office 365 API と Outlook.com API の認証 | MSDN
今回、自分で登録したカスタムアプリを認証API v2で認証しようとしたところ、ブラウザバーに
Application+[クライアントID]+is+not+supported+for+this+API+version.
という表記が返り、エラーとなってしまった。おそらく、アプリケーションにめちゃくちゃ権限を付与してしまい、その権限のうち1つが認証API v2ではノンサポだからではないか。…となると、認証APIのバージョンによって使える機能も違うという事?認証API 1.0専用の権限をアプリに付与してしまうと、認証API 2.0で許可されない?
ということで、認証API v1.0だけで進めることにします。
メモ:参考にした記事
- Office 365 API 入門 – Tsmatz
- Get Started with the Outlook REST APIs – Outlook Dev Center
- Using PowerShell and the Office 365 REST API with OAuth. – Ron Ben Artzi
v2が出て一年以内だからか、v1とv2が混在してるのでややこしい。
4. プログラムからアクセス
3.で取得した認証トークンを元に、postを投げてやる
$url = 'https://login.microsoftonline.com/common/oauth2/token' $Body = @{ "grant_type" = "authorization_code" "code" = [認証コード] "client_id" = [クライアントID] "client_secret" = [クライアント秘密鍵] "redirect_uri" = "https://localhost/myapp" "resource" = "https://outlook.office365.com/" } $ContentType = "application/x-www-form-urlencoded" Invoke-RestMethod -uri $url -Method Post -Body $body -ContentType $ContentType
結果、
token_type : Bearer scope : Calendars.Read Calendars.Read.All Calendars.Read.Shared Calendars.ReadWrite Calendars.ReadWrite.All Calendars.ReadWrite.Shared Contacts.Read Contacts.Read.All Contacts.Read.Shared Contacts.ReadWrite Contacts.ReadWrite.All Contacts.ReadWrite.Shared Directory.AccessAsUser.All Directory.Read.All Directory.ReadWrite.All email Exchange.Manage Files.Read Files.Read.All Files.Read.Selected Files.ReadWrite Files.ReadWrite.All Files.ReadWrite.AppFolder Files.ReadWrite.Selected full_access_as_user Group.Read.All Group.ReadWrite.All IdentityRiskEvent.Read.All Mail.Read Mail.Read.All Mail.Read .Shared Mail.ReadWrite Mail.ReadWrite.All Mail.ReadWrite.Shared Mail.Send Mail.Send.All Mail.Send.Shared MailboxSettings.ReadWrite Notes.Create Notes.Read Notes.Read.All Notes.ReadWrite Notes.ReadWrite.All Notes.ReadWrite.CreatedByApp offline_access openid People.Read People.ReadWrite profile Reports.Read.All Sites.Read.All Sites.ReadWrite.All Tasks.Read Tasks.Read.Shared Tasks.ReadWrite Tasks.ReadWrite.Shared User.Read User.Read.All User.ReadBasic.All User.ReadWrite User.ReadWrite.All expires_in : 3600 ext_expires_in : 0 expires_on : 1478335851 not_before : 1478331951 resource : https://outlook.office365.com/ access_token : アクセストークン refresh_token : リフレッショトークン id_token : IDトークン
権限めっちゃついてるw 自分でつけたんだけど…。
注意
サンプルコードに"resource"の指定がなかったため抜かすと、
“error":"invalid_resource","error_description":"AADSTS50001: Resource identifier is not provided.\r\nTrace ID
みたいなエラーが出た。エラーコード"AADSTS50001″でググると以下のURLがヒット(ppt注意)
Cloud Authentication Troubleshooting and Recipes for Developers
結論としては、resourceの指定は必要でした。
疲れたので今日はここまで。
ディスカッション
コメント一覧
まだ、コメントがありません