前回に続いてWindows Live ID SDKよりWindows Live ID Delegated Authentication
承認要求ページと承認管理ページ
はじめにユーザーが目にする承認要求ページについて確認しておきましょう。Webサイト
![図1 承認要求ページ 図1 承認要求ページ](/assets/images/dev/serial/01/wl-sdk/0014/thumb/TH800_0014-02.png)
承認要求ページでは、
ユーザーがアクセス許可を取り消したい場合は、
![図2 承認管理ページ 図2 承認管理ページ](/assets/images/dev/serial/01/wl-sdk/0015/thumb/TH800_0015-01.png)
承認情報の受信
それでは、
- ResponseCode
承認要求の状態を表す応答コードです。次のいずれかが格納されています。
値 説明 RequestApproved ユーザーは承認要求プロセスを完了 RequestRejected ユーザーは承認要求プロセスをキャンセル アプリケーションプロバイダが要求した許可に対して、
すべてまたは一部を許可した場合に 「RequestApproved」 の文字列が格納されています。 - ConsentToken
承認トークンです。承認要求を完了した場合のみ返されます。このトークンにはさらに複数のパラメータが含まれています。アプリケーションプロバイダはこの情報を使用してリソースプロバイダにアクセスします。構造の解析はこの後説明します。
- action
ユーザーの実行中の操作を表す文字列が格納されています。現在のところ格納される可能性がある値は次のひとつのみです。
値 説明 delauth ユーザーが承認要求のプロセス完了に成功 - appctx
承認の要求時に指定したappctxパラメータの値が格納されています。
ResponseCodeの値が
委任認証プロセスにおいて必須の処理の中で、
承認トークンの構造
承認トークンの文字列はURLデコードすると
- eact
暗号化された承認トークンです。アプリケーション検証トークンを指定した場合もしくはアプリケーション登録がされている場合は、
承認トークンが暗号化されています。この値を復号すると次のパラメータがさらに格納されています。 - delt
委任トークンと呼ばれる文字列です。アプリケーションプロバイダがリソースプロバイダに渡すトークンになり、
リソースプロバイダはこのトークンを使用して承認情報を検証します。この委任トークンはすぐに有効期限切れになり使用できなくなります。 - reft
更新トークンと呼ばれる文字列です。委任トークンの有効期限が切れた場合、
承認を更新し、 新たな委任トークンを取得するために使用するトークンになります。アプリケーション検証トークンを使用せずに承認トークンを受信した場合、 この更新トークンがない場合があるようです。 - skey
セッションキーと呼ばれる文字列になります。アプリケーションプロバイダはこの値を必要としません。
- offer
ユーザーが承認したオファーとアクション、
その有効期限が格納されています。例を以下に示します。 SpacesPhotos.
ReadWrite:1249915138;ContactsSync. FullSync:1218985740;ApplicationStorage. ReadWrite:1249929098 オファーとアクションはピリオド
(.) で結ばれ、 その後ろにコロン (:) が付き1970年1月1日 (UTC) からの経過秒として有効期限が表わされています。複数のオファーとアクションがある場合は、 セミコロンで (;) で区切られています。 - exp
委任トークンの有効期限が1970年1月1日
(UTC) からの経過秒として格納されています。委任トークンの有効期限が切れた場合、 更新トークンを使い新しい委任トークンの取得ができます。 - lid
リソースプロバイダのユーザーデータの場所を表す識別子になります。当然ながらユーザーごとに異なり、
この値によりユーザー個人のデータにアクセスできます。この値からユーザーのWindows Live IDアカウントは類推できません。
パラメータは以上です。承認トークンは、
承認トークンの復号化
アプリケーション検証トークンを使用した場合などPOSTデータに含まれている承認トークンが暗号化されている場合がありました。ここでは承認トークンの復号手順をコードで示します。言語はVB.
まずは利便性のために
Public Shared Function Parse(ByVal input As String) As Specialized.NameValueCollection
Dim pairs As New Specialized.NameValueCollection
Dim pairValues() As String = input.Split(New Char() {"&"c})
For Each value As String In pairValues
Dim separator As Integer = value.IndexOf("=")
If separator = -1 OrElse separator = value.Length Then
Continue For
End If
pairs(value.Substring(0, separator)) = value.Substring(separator + 1)
Next
Return pairs
End Function
復号にはAES
共有キーの作成は、
' Imports System.Security.Cryptography
Public Shared Function Derive(ByVal secretKey As String, ByVal prefix As String) As Byte()
Dim hashAlgorithm As New SHA256Managed
Dim buffer() As Byte = System.Text.Encoding.Default.GetBytes(prefix & secretKey)
Dim hashOutput() As Byte = hashAlgorithm.ComputeHash(buffer)
Dim byteKey(15) As Byte
Array.Copy(hashOutput, byteKey, byteKey.Length)
Return byteKey
End Function
以上を踏まえた承認トークンを復号化するメソッドは次のようになります。例外処理は省略しています。
Public Shared Function DecryptToken(ByVal token As String, ByVal secretKey As String) As String
Dim aesAlg As New RijndaelManaged
aesAlg.KeySize = 128
aesAlg.Key = Derive(secretKey, "ENCRYPTION")
aesAlg.Padding = PaddingMode.PKCS7
Dim ivAndEncryptedValue() As Byte = Convert.FromBase64String(HttpUtility.UrlDecode(token))
Dim memoryStream As New System.IO.MemoryStream(ivAndEncryptedValue)
Dim iv(15) As Byte
memoryStream.Read(iv, 0, iv.Length)
aesAlg.IV = iv
Using cryptoStream As New CryptoStream(memoryStream, aesAlg.CreateDecryptor, CryptoStreamMode.Read), _
streamReader As New System.IO.StreamReader(cryptoStream, System.Text.Encoding.ASCII)
Return streamReader.ReadToEnd
End Using
End Function
Webページ上に取得した承認トークンの各パラメータ値を表示するコードは次のようになります。
<div>
<%
Dim consentToken As String = Request.Params("ConsentToken")
If consentToken <> "" Then
Dim pairs As Specialized.NameValueCollection = Parse(HttpUtility.UrlDecode(consentToken))
For Each key As String In pairs.Keys
Page.Response.Write(String.Format("{0}: {1}<br />", key, pairs(key)))
Next
If pairs("eact") <> "" Then
consentToken = DecryptToken(pairs("eact"), "****SecretKey****")
pairs = Parse(HttpUtility.UrlDecode(consentToken))
For Each key As String In pairs.Keys
Page.Response.Write(String.Format("{0}: {1}<br />", key, pairs(key)))
Next
End If
End If
%>
</div>
承認の更新
承認トークン内に含まれていた委任トークンは、
通常は取得した委任トークンをアプリケーションプロバイダが保存しておき、
新しい委任トークンを取得するには、
ユーザーの操作
(承諾など) がない JSON
(JavaScript ObjectNotation) 形式で情報が返ってくる
承認要求では、
以上のように更新処理はJavaScriptのみを使用したやり取りが可能になり、
さて、
- ru
更新された委任トークンを受け取るURL指定します。URLは完全修飾のドメイン名
(例: www. gihyo. jp) を使用し、 クエリ文字列のパラメータが含まれていてはいけません。このパラメータはアプリケーション登録がされている場合、 省略できます。 - ps
アプリケーションプロバイダが必要とする許可
(オファーとアクション) を表す文字列を指定します。 - reft
更新トークンを指定します。今回紹介した承認情報の取得にて得られた承認トークンに含まれている更新トークンと呼ばれる文字列を指定します。
- app
アプリケーション検証トークンを指定します。これは承認要求のときにも指定したものです。アプリケーションが登録してありアプリケーション検証を必須に設定してある場合にこのパラメータが必要になります。アプリケーション検証トークンの作成方法は前回紹介しています。
承認更新情報の受信
承認の更新時、
- ConsentToken
承認トークンです。構造は先に示したものと同じです。有効な期限付きの委任トークンが含まれています。実際にはJSON形式のため次のような形式の文字列として取得されます。
{"ConsentToken":"eact%3D…"}
- error
承認更新時に何らかのエラーが発生した場合は、
そのエラー内容を示す番号が返ってきます。例えば次のような文字列です。 {"error":"2000"}
エラー番号の内容は、
MSDNライブラリ内のエラーコードを参照してください。
次に承認更新を行うVB.
' Imports System.Net
Dim ps As String = "SpacesPhotos.ReadWrite,ContactsSync.FullSync,ApplicationStorage.ReadWrite"
Dim reft As String = HttpUtility.UrlDecode("更新トークン")
' GetAppVerifierToken, GetTimestamp メソッドは前回の記事を参照
Dim app As String = GetAppVerifierToken("****Application ID****", "****SecretKey****", GetTimestamp)
Dim path As String = String.Format("https://consent.live.com/RefreshToken.aspx?ps={0}&reft={1}&app={2}", ps, reft, app)
Dim req As HttpWebRequest = DirectCast(WebRequest.Create(path), HttpWebRequest)
Try
Dim json As String
Using response As HttpWebResponse = DirectCast(req.GetResponse, HttpWebResponse), _
stream As New System.IO.StreamReader(response.GetResponseStream)
json = stream.ReadToEnd
End Using
Response.Write(json)
Catch webEx As WebException
Response.Write(webEx.Message)
Catch ex As Exception
Response.Write(ex.Message)
End Try
サンプルコード
最後に委任認証のサンプルコードについて紹介しておきます。Windows Live IDDelegated Authentication SDK 1.
委任認証については今回でおわりです。委任認証の使い方は理解いただけたでしょうか。前回と今回の内容だけではアプリケーションとしてはまだ何もできません。次回から委任認証を利用してWindows Live サービス上のユーザーデータにアクセスしてみたいと思います。