UP by Jawbone のライフログを Windows アプリで取得する(2)の続きです
OAuth 2.0 の処理の流れはわかりましたが、途中のリダイレクト後の Uri 取得をどうするかが未解決でした
とりあえずリダイレクト前までの処理を進めてみます
設定チャームからデバイス連携の OAuth 認証を通すため、646 px の設定ポップアップを作成します
中身は下記のような WebView があるだけの単純なものです
<SettingsFlyout x:Class="LifelogViewer.Views.Flyout.OAuthFlyout" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="using:LifelogViewer.Views.Flyout" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="UP 連携設定" Width="646" IconSource="Assets/SmallLogo.png" d:DesignWidth="646" mc:Ignorable="d"> <StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <StackPanel Style="{StaticResource SettingsFlyoutSectionStyle}"> <TextBlock Style="{StaticResource TitleTextBlockStyle}" Text="Jawbone とこのアプリの連携設定が必要です" /> <TextBlock Margin="0,0,0,25" Style="{StaticResource BodyTextBlockStyle}" TextWrapping="Wrap"> <TextBlock.Text>UP アカウントでサインイン後、このアプリが Jawbone のライフログにアクセスすることを許可してください</TextBlock.Text> </TextBlock> <WebView x:Name="webView" Height="500" /> </StackPanel> </StackPanel> </SettingsFlyout>
次に通信がらみの処理を行うサービスクラスを下記のように作りました
/// <summary> /// Jawbone アクセスサービス /// </summary> public class JawboneService { /// <summary> /// トークン要求 Uri /// </summary> private static readonly string RequestTokenBaseUri = @"https://jawbone.com/auth/oauth2/auth?response_type=code&client_id={0}&scope={1}&redirect_uri={2}"; /// <summary> /// Client ID /// </summary> private static readonly string ClientId = @"登録アプリの値を設定"; /// <summary> /// トークン要求用 Uri を構成する /// </summary> /// <returns>トークン要求用 Uri</returns> public string GetRequestTokenUri() { return string.Format(RequestTokenBaseUri, Uri.EscapeDataString(ClientId), Uri.EscapeDataString(Scopes), Uri.EscapeDataString(RedirectUri)); } }
あとは設定ポップアップ遷移時の処理を記載します
/// <summary> /// OAuth 認証用ポップアップ /// </summary> public sealed partial class OAuthFlyout : SettingsFlyout { /// <summary> /// コンストラクタ /// </summary> public OAuthFlyout() { this.InitializeComponent(); this.Loaded += this.OnLoaded; this.Unloaded += this.OnUnloaded; } /// <summary> /// 破棄時の処理 /// </summary> /// <param name="sender">イベント発行者</param> /// <param name="e">イベント引数</param> private void OnUnloaded(object sender, RoutedEventArgs e) { this.Unloaded -= this.OnUnloaded; this.Loaded -= this.OnLoaded; this.webView.NavigationCompleted -= this.OnNavigationCompleted; } /// <summary> /// 読み込み時の処理 /// </summary> /// <param name="sender">イベント発行者</param> /// <param name="e">イベント引数</param> private void OnLoaded(object sender, RoutedEventArgs e) { this.webView.NavigationCompleted += this.OnNavigationCompleted; this.webView.Navigate(new Uri(App.JawboneService.GetRequestTokenUri())); } /// <summary> /// WebView 遷移完了時の処理 /// </summary> /// <param name="sender">イベント発行者</param> /// <param name="e">イベント引数</param> private async void OnNavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args) { // 遷移前の画面がアクセス許可画面だった場合 if (args.Uri.ToString().StartsWith("https://jawbone.com/auth/oauth2/auth_permission")) { // WebView の読み込みが完了するまでウェイト await Task.Delay(500); // WebView 内で JavaScript を経由して Uri を取得 var uri = await this.webView.InvokeScriptAsync("eval", new string[] { "location.href" }); } } }
ポイントは最後の OnNavigationCompleted の部分
/// <summary> /// WebView 遷移完了時の処理 /// </summary> /// <param name="sender">イベント発行者</param> /// <param name="e">イベント引数</param> private async void OnNavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args) { // 遷移前の画面がアクセス許可画面だった場合 if (args.Uri.ToString().StartsWith("https://jawbone.com/auth/oauth2/auth_permission")) { // WebView の読み込みが完了するまでウェイト await Task.Delay(500); // WebView 内で JavaScript を経由して Uri を取得 var uri = await this.webView.InvokeScriptAsync("eval", new string[] { "location.href" }); } }
途中で https://localhost:5555 にリダイレクトされると画面遷移に失敗した状態でこちらのイベントハンドラにやってきます
このとき WebView の args.Uri を見ても遷移に失敗したので、遷移前の Uri しか取得できないのですが、JavaScript で強引に location.href を取得しています
実行して動作を確かめてみます
設定ポップアップでまずサインイン画面が表示され
サインインするとアクセス許可画面に遷移、ここで「同意する」を選ぶと
リダイレクトされて code のクエリストリング付きの Uri がとれました!
Web アプリじゃなくても OAuth 認証が通せそうです
次回はこの code からアクセストークンを取得しようと思います