OSDN Git Service

HttpTwitter.SendDirectMessageメソッドをTwitterApiクラスに置き換え
[opentween/open-tween.git] / OpenTween / Connection / HttpConnectionOAuth.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 //           (c) 2008-2011 Moz (@syo68k)
4 //           (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
5 //           (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 //           (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
7 //           (c) 2011      spinor (@tplantd) <http://d.hatena.ne.jp/spinor/>
8 // All rights reserved.
9 // 
10 // This file is part of OpenTween.
11 // 
12 // This program is free software; you can redistribute it and/or modify it
13 // under the terms of the GNU General Public License as published by the Free
14 // Software Foundation; either version 3 of the License, or (at your option)
15 // any later version.
16 // 
17 // This program is distributed in the hope that it will be useful, but
18 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 // for more details. 
21 // 
22 // You should have received a copy of the GNU General Public License along
23 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
24 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
25 // Boston, MA 02110-1301, USA.
26
27 using HttpConnection = OpenTween.HttpConnection;
28 using IHttpConnection = OpenTween.IHttpConnection;
29 using OAuthUtility = OpenTween.Connection.OAuthUtility;
30 using DateTime = System.DateTime;
31 using DateTimeKind = System.DateTimeKind;
32 using Random = System.Random;
33 using HttpWebRequest = System.Net.HttpWebRequest;
34 using HttpStatusCode = System.Net.HttpStatusCode;
35 using Uri = System.Uri;
36 using System.Collections.Generic; // for Dictionary<TKey, TValue>, List<T>, KeyValuePair<TKey, TValue>, SortedDictionary<TKey, TValue>
37 using CallbackDelegate = OpenTween.CallbackDelegate;
38 using StackFrame = System.Diagnostics.StackFrame;
39 using FileInfo = System.IO.FileInfo;
40 using Stream = System.IO.Stream;
41 using HttpWebResponse = System.Net.HttpWebResponse;
42 using WebException = System.Net.WebException;
43 using WebExceptionStatus = System.Net.WebExceptionStatus;
44 using Exception = System.Exception;
45 using NameValueCollection = System.Collections.Specialized.NameValueCollection;
46 using Convert = System.Convert;
47 using InvalidDataException = System.IO.InvalidDataException;
48 using UriBuilder = System.UriBuilder;
49 using Environment = System.Environment;
50 using StringBuilder = System.Text.StringBuilder;
51 using HttpRequestHeader = System.Net.HttpRequestHeader;
52 using HMACSHA1 = System.Security.Cryptography.HMACSHA1;
53 using Encoding = System.Text.Encoding;
54 using System;
55
56 namespace OpenTween
57 {
58         /// <summary>
59         /// OAuth認証を使用するHTTP通信。HMAC-SHA1固定
60         /// </summary>
61         /// <remarks>
62         /// 使用前に認証情報を設定する。認証確認を伴う場合はAuthenticate系のメソッドを、認証不要な場合はInitializeを呼ぶこと。
63         /// </remarks>
64         abstract public class HttpConnectionOAuth : HttpConnection, IHttpConnection
65         {
66                 /// <summary>
67                 /// OAuthのアクセストークン。永続化可能(ユーザー取り消しの可能性はある)。
68                 /// </summary>
69                 private string token = "";
70
71                 /// <summary>
72                 /// OAuthの署名作成用秘密アクセストークン。永続化可能(ユーザー取り消しの可能性はある)。
73                 /// </summary>
74                 private string tokenSecret = "";
75
76                 /// <summary>
77                 /// OAuthのコンシューマー鍵
78                 /// </summary>
79                 protected string consumerKey;
80
81                 /// <summary>
82                 /// OAuthの署名作成用秘密コンシューマーデータ
83                 /// </summary>
84                 protected string consumerSecret;
85
86                 /// <summary>
87                 /// 認証成功時の応答でユーザー情報を取得する場合のキー。設定しない場合は、AuthUsernameもブランクのままとなる
88                 /// </summary>
89                 private string userIdentKey = "";
90
91                 /// <summary>
92                 /// 認証成功時の応答でユーザーID情報を取得する場合のキー。設定しない場合は、AuthUserIdもブランクのままとなる
93                 /// </summary>
94                 private string userIdIdentKey = "";
95
96                 /// <summary>
97                 /// 認証完了時の応答からuserIdentKey情報に基づいて取得するユーザー情報
98                 /// </summary>
99                 private string authorizedUsername = "";
100
101                 /// <summary>
102                 /// 認証完了時の応答からuserIdentKey情報に基づいて取得するユーザー情報
103                 /// </summary>
104                 private long authorizedUserId;
105
106                 /// <summary>
107                 /// Stream用のHttpWebRequest
108                 /// </summary>
109                 private HttpWebRequest streamReq = null;
110
111                 /// <summary>
112                 /// OAuth認証で指定のURLとHTTP通信を行い、結果を返す
113                 /// </summary>
114                 /// <param name="method">HTTP通信メソッド(GET/HEAD/POST/PUT/DELETE)</param>
115                 /// <param name="requestUri">通信先URI</param>
116                 /// <param name="param">GET時のクエリ、またはPOST時のエンティティボディ</param>
117                 /// <param name="content">[OUT]HTTP応答のボディデータ</param>
118                 /// <param name="headerInfo">[IN/OUT]HTTP応答のヘッダ情報。必要なヘッダ名を事前に設定しておくこと</param>
119                 /// <param name="callback">処理終了直前に呼ばれるコールバック関数のデリゲート 不要な場合はnullを渡すこと</param>
120                 /// <returns>HTTP応答のステータスコード</returns>
121                 public HttpStatusCode GetContent( string method,
122                                                   Uri requestUri,
123                                                   Dictionary< string, string > param,
124                                                   ref string content,
125                                                   Dictionary< string, string > headerInfo,
126                                                   CallbackDelegate callback )
127                 {
128                         // 認証済かチェック
129                         if ( string.IsNullOrEmpty( token ) )
130                                 return HttpStatusCode.Unauthorized;
131
132                         HttpWebRequest webReq = this.CreateRequest( method, requestUri, param, gzip: true );
133                         // OAuth認証ヘッダを付加
134                         this.AppendOAuthInfo( webReq, param, token, tokenSecret );
135
136                         HttpStatusCode code;
137                         if ( content == null )
138                                 code = this.GetResponse( webReq, headerInfo );
139                         else
140                                 code = this.GetResponse( webReq, out content, headerInfo );
141
142                         if ( callback != null )
143                         {
144                                 StackFrame frame = new StackFrame( 1 );
145                                 callback( frame.GetMethod().Name, code, headerInfo, content );
146                         }
147                         return code;
148                 }
149
150                 /// <summary>
151                 /// バイナリアップロード
152                 /// </summary>
153                 public HttpStatusCode GetContent( string method,
154                                                   Uri requestUri,
155                                                   Dictionary< string, string > param,
156                                                   List< KeyValuePair< string, IMediaItem > > binary, 
157                                                   ref string content,
158                                                   Dictionary< string, string > headerInfo,
159                                                   CallbackDelegate callback )
160                 {
161                         // 認証済かチェック
162                         if ( string.IsNullOrEmpty( token ) )
163                                 return HttpStatusCode.Unauthorized;
164
165                         HttpWebRequest webReq = this.CreateRequest( method, requestUri, param, binary );
166                         // OAuth認証ヘッダを付加
167                         this.AppendOAuthInfo( webReq, null, token, tokenSecret );
168
169                         HttpStatusCode code;
170                         if ( content == null )
171                                 code = this.GetResponse( webReq, headerInfo );
172                         else
173                                 code = this.GetResponse( webReq, out content, headerInfo );
174
175                         if ( callback != null )
176                         {
177                                 StackFrame frame = new StackFrame( 1 );
178                                 callback( frame.GetMethod().Name, code, headerInfo, content );
179                         }
180                         return code;
181                 }
182
183                 /// <summary>
184                 /// OAuth認証で指定のURLとHTTP通信を行い、ストリームを返す
185                 /// </summary>
186                 /// <param name="method">HTTP通信メソッド(GET/HEAD/POST/PUT/DELETE)</param>
187                 /// <param name="requestUri">通信先URI</param>
188                 /// <param name="param">GET時のクエリ、またはPOST時のエンティティボディ</param>
189                 /// <param name="content">[OUT]HTTP応答のボディストリーム</param>
190                 /// <returns>HTTP応答のステータスコード</returns>
191                 public HttpStatusCode GetContent( string method,
192                                                   Uri requestUri,
193                                                   Dictionary< string, string > param,
194                                                   ref Stream content,
195                                                   string userAgent )
196                 {
197                         // 認証済かチェック
198                         if ( string.IsNullOrEmpty( token ) )
199                                 return HttpStatusCode.Unauthorized;
200
201                         this.RequestAbort();
202                         this.streamReq = this.CreateRequest( method, requestUri, param );
203                         // User-Agent指定がある場合は付加
204                         if ( !string.IsNullOrEmpty( userAgent ) )
205                                 this.streamReq.UserAgent = userAgent;
206
207                         // OAuth認証ヘッダを付加
208                         this.AppendOAuthInfo( this.streamReq, param, token, tokenSecret );
209
210                         try
211                         {
212                                 HttpWebResponse webRes = (HttpWebResponse)this.streamReq.GetResponse();
213                                 content = webRes.GetResponseStream();
214                                 return webRes.StatusCode;
215                         }
216                         catch ( WebException ex )
217                         {
218                                 if ( ex.Status == WebExceptionStatus.ProtocolError )
219                                 {
220                                         HttpWebResponse res = (HttpWebResponse)ex.Response;
221                                         return res.StatusCode;
222                                 }
223                                 throw;
224                         }
225                 }
226
227                 public void RequestAbort()
228                 {
229                         try
230                         {
231                                 if ( this.streamReq != null )
232                                 {
233                                         this.streamReq.Abort();
234                                         this.streamReq = null;
235                                 }
236                         }
237                         catch ( Exception ) {}
238                 }
239
240                 #region "認証処理"
241                 /// <summary>
242                 /// OAuth認証の開始要求(リクエストトークン取得)。PIN入力用の前段
243                 /// </summary>
244                 /// <remarks>
245                 /// 呼び出し元では戻されたurlをブラウザで開き、認証完了後PIN入力を受け付けて、リクエストトークンと共にAuthenticatePinFlowを呼び出す
246                 /// </remarks>
247                 /// <param name="requestTokenUrl">リクエストトークンの取得先URL</param>
248                 /// <param name="authorizeUrl">ブラウザで開く認証用URLのベース</param>
249                 /// <param name="requestToken">[OUT]認証要求で戻されるリクエストトークン。使い捨て</param>
250                 /// <param name="authUri">[OUT]requestUriを元に生成された認証用URL。通常はリクエストトークンをクエリとして付加したUri</param>
251                 /// <returns>取得結果真偽値</returns>
252                 public bool AuthenticatePinFlowRequest( string requestTokenUrl, string authorizeUrl, ref string requestToken, ref Uri authUri )
253                 {
254                         // PIN-based flow
255             authUri = this.GetAuthenticatePageUri( requestTokenUrl, authorizeUrl, ref requestToken );
256                         if ( authUri == null )
257                                 return false;
258                         return true;
259                 }
260
261                 /// <summary>
262                 /// OAuth認証のアクセストークン取得。PIN入力用の後段
263                 /// </summary>
264                 /// <remarks>
265                 /// 事前にAuthenticatePinFlowRequestを呼んで、ブラウザで認証後に表示されるPINを入力してもらい、その値とともに呼び出すこと
266                 /// </remarks>
267                 /// <param name="accessTokenUrl">アクセストークンの取得先URL</param>
268                 /// <param name="requestToken">AuthenticatePinFlowRequestで取得したリクエストトークン</param>
269                 /// <param name="pinCode">Webで認証後に表示されるPINコード</param>
270                 /// <returns>取得結果真偽値</returns>
271                 public HttpStatusCode AuthenticatePinFlow( string accessTokenUrl, string requestToken, string pinCode )
272                 {
273                         // PIN-based flow
274                         if ( string.IsNullOrEmpty( requestToken ) )
275                                 throw new InvalidOperationException( "Sequence error.(requestToken is blank)" );
276
277                         // アクセストークン取得
278                         string content = "";
279                         NameValueCollection accessTokenData;
280                         HttpStatusCode httpCode = this.GetOAuthToken( new Uri( accessTokenUrl ), pinCode, requestToken, null, ref content );
281                         if ( httpCode != HttpStatusCode.OK )
282                                 return httpCode;
283                         accessTokenData = base.ParseQueryString( content );
284
285                         if ( accessTokenData != null )
286                         {
287                                 this.token = accessTokenData[ "oauth_token" ];
288                                 this.tokenSecret = accessTokenData[ "oauth_token_secret" ];
289
290                                 // サービスごとの独自拡張対応
291                                 if ( !string.IsNullOrEmpty(this.userIdentKey) )
292                                         this.authorizedUsername = accessTokenData[ this.userIdentKey ];
293                                 else
294                                         this.authorizedUsername = "";
295
296                                 if ( !string.IsNullOrEmpty(this.userIdIdentKey) )
297                                 {
298                                         try
299                                         {
300                                                 this.authorizedUserId = Convert.ToInt64( accessTokenData[ this.userIdIdentKey ] );
301                                         }
302                                         catch ( Exception )
303                                         {
304                                                 this.authorizedUserId = 0;
305                                         }
306                                 }
307                                 else
308                                 {
309                                         this.authorizedUserId = 0;
310                                 }
311
312                                 if ( string.IsNullOrEmpty(token) )
313                                         throw new InvalidDataException( "Token is null." );
314                                 return HttpStatusCode.OK;
315                         }
316                         else
317                         {
318                 throw new InvalidDataException( "Return value is null." );
319                         }
320                 }
321
322         public HttpStatusCode Authenticate(Uri accessTokenUrl, string username, string password, ref string content)
323         {
324             return this.AuthenticateXAuth(accessTokenUrl, username, password, ref content);
325         }
326
327                 /// <summary>
328                 /// OAuth認証のアクセストークン取得。xAuth方式
329                 /// </summary>
330                 /// <param name="accessTokenUrl">アクセストークンの取得先URL</param>
331                 /// <param name="username">認証用ユーザー名</param>
332                 /// <param name="password">認証用パスワード</param>
333                 /// <returns>取得結果真偽値</returns>
334                 public HttpStatusCode AuthenticateXAuth( Uri accessTokenUrl, string username, string password, ref string content )
335                 {
336                         // ユーザー・パスワードチェック
337                         if ( string.IsNullOrEmpty( username ) )
338                                 throw new ArgumentException( "username is null or empty", nameof(username) );
339             if ( string.IsNullOrEmpty( password ) )
340                 throw new ArgumentException( "password is null or empty", nameof(password) );
341
342                         // xAuthの拡張パラメータ設定
343                         Dictionary< string, string > parameter = new Dictionary< string, string >();
344                         parameter.Add( "x_auth_mode", "client_auth" );
345                         parameter.Add( "x_auth_username", username );
346                         parameter.Add( "x_auth_password", password );
347
348                         // アクセストークン取得
349                         HttpStatusCode httpCode = this.GetOAuthToken( accessTokenUrl, "", "", parameter, ref content );
350                         if ( httpCode != HttpStatusCode.OK )
351                                 return httpCode;
352                         NameValueCollection accessTokenData = base.ParseQueryString( content );
353
354                         if ( accessTokenData != null )
355                         {
356                                 this.token = accessTokenData[ "oauth_token" ];
357                                 this.tokenSecret = accessTokenData[ "oauth_token_secret" ];
358
359                                 // サービスごとの独自拡張対応
360                                 if ( !string.IsNullOrEmpty(this.userIdentKey) )
361                                         this.authorizedUsername = accessTokenData[ this.userIdentKey ];
362                                 else
363                                         this.authorizedUsername = "";
364
365                                 if ( !string.IsNullOrEmpty(this.userIdIdentKey) )
366                                 {
367                                         try
368                                         {
369                         this.authorizedUserId = Convert.ToInt64( accessTokenData[ this.userIdIdentKey ] );
370                                         }
371                                         catch ( Exception )
372                                         {
373                                                 this.authorizedUserId = 0;
374                                         }
375                                 }
376                                 else
377                                 {
378                                         this.authorizedUserId = 0;
379                                 }
380
381                                 if ( string.IsNullOrEmpty(token) )
382                                         throw new InvalidDataException( "Token is null." );
383                                 return HttpStatusCode.OK;
384                         }
385                         else
386                         {
387                                 throw new InvalidDataException( "Return value is null." );
388                         }
389                 }
390
391                 /// <summary>
392                 /// OAuth認証のリクエストトークン取得。リクエストトークンと組み合わせた認証用のUriも生成する
393                 /// </summary>
394                 /// <param name="requestTokenUrl">リクエストトークンの取得先URL</param>
395                 /// <param name="authorizeUrl">ブラウザで開く認証用URLのベース</param>
396                 /// <param name="requestToken">[OUT]取得したリクエストトークン</param>
397                 /// <returns>取得結果真偽値</returns>
398                 private Uri GetAuthenticatePageUri( string requestTokenUrl, string authorizeUrl, ref string requestToken )
399                 {
400                         const string tokenKey = "oauth_token";
401
402                         // リクエストトークン取得
403                         string content = "";
404                         NameValueCollection reqTokenData;
405                         if ( this.GetOAuthToken( new Uri( requestTokenUrl ), "", "", null, ref content, callbackUrl: "oob" ) != HttpStatusCode.OK )
406                                 return null;
407                         reqTokenData = base.ParseQueryString( content );
408
409                         if ( reqTokenData != null )
410                         {
411                                 requestToken = reqTokenData[ tokenKey ];
412                                 // Uri生成
413                                 UriBuilder ub = new UriBuilder( authorizeUrl );
414                                 ub.Query = string.Format( "{0}={1}", tokenKey, requestToken );
415                                 return ub.Uri;
416                         }
417                         else
418                         {
419                                 return null;
420                         }
421                 }
422
423                 /// <summary>
424                 /// OAuth認証のトークン取得共通処理
425                 /// </summary>
426                 /// <param name="requestUri">各種トークンの取得先URL</param>
427                 /// <param name="pinCode">PINフロー時のアクセストークン取得時に設定。それ以外は空文字列</param>
428                 /// <param name="requestToken">PINフロー時のリクエストトークン取得時に設定。それ以外は空文字列</param>
429                 /// <param name="parameter">追加パラメータ。xAuthで使用</param>
430                 /// <returns>取得結果のデータ。正しく取得出来なかった場合はNothing</returns>
431                 private HttpStatusCode GetOAuthToken( Uri requestUri, string pinCode, string requestToken, Dictionary< string , string > parameter, ref string content, string callbackUrl = null )
432                 {
433                         HttpWebRequest webReq = null;
434                         // HTTPリクエスト生成。PINコードもパラメータも未指定の場合はGETメソッドで通信。それ以外はPOST
435                         if ( string.IsNullOrEmpty( pinCode ) && parameter != null )
436                                 webReq = this.CreateRequest( "GET", requestUri, null );
437                         else
438                                 webReq = this.CreateRequest( "POST", requestUri, parameter ); // ボディに追加パラメータ書き込み
439
440                         // OAuth関連パラメータ準備。追加パラメータがあれば追加
441                         Dictionary< string, string > query = new Dictionary< string, string >();
442                         if ( parameter != null )
443                                 foreach ( KeyValuePair< string, string > kvp in parameter )
444                                         query.Add( kvp.Key, kvp.Value );
445
446                         // PINコードが指定されていればパラメータに追加
447                         if ( ! string.IsNullOrEmpty( pinCode ) )
448                                 query.Add( "oauth_verifier", pinCode );
449
450                         // コールバックURLが指定されていればパラメータに追加
451                         if (!string.IsNullOrEmpty(callbackUrl))
452                                 query.Add("oauth_callback", callbackUrl);
453
454                         // OAuth関連情報をHTTPリクエストに追加
455                         this.AppendOAuthInfo( webReq, query, requestToken, "" );
456
457                         // HTTP応答取得
458                         Dictionary< string, string > header = new Dictionary< string, string >() { { "Date", "" } };
459                         HttpStatusCode responseCode = this.GetResponse( webReq, out content, header );
460                         if ( responseCode == HttpStatusCode.OK )
461                                 return responseCode;
462
463                         if ( !string.IsNullOrEmpty( header[ "Date" ] ) )
464                                 content += Environment.NewLine + "Check the Date & Time of this computer." + Environment.NewLine
465                                 + "Server:" + DateTime.Parse( header[ "Date" ] ).ToString() + "  PC:" + DateTime.Now.ToString();
466                         return responseCode;
467                 }
468                 #endregion // 認証処理
469
470                 #region "OAuth認証用ヘッダ作成・付加処理"
471                 /// <summary>
472                 /// HTTPリクエストにOAuth関連ヘッダを追加
473                 /// </summary>
474                 /// <param name="webRequest">追加対象のHTTPリクエスト</param>
475                 /// <param name="query">OAuth追加情報+クエリ or POSTデータ</param>
476                 /// <param name="token">アクセストークン、もしくはリクエストトークン。未取得なら空文字列</param>
477                 /// <param name="tokenSecret">アクセストークンシークレット。認証処理では空文字列</param>
478                 protected virtual void AppendOAuthInfo( HttpWebRequest webRequest, Dictionary< string, string > query, string token, string tokenSecret )
479                 {
480                         var credential = OAuthUtility.CreateAuthorization( webRequest.Method, webRequest.RequestUri, query,
481                                 this.consumerKey, this.consumerSecret, token, tokenSecret );
482
483                         webRequest.Headers.Add( HttpRequestHeader.Authorization, credential );
484                 }
485                 #endregion // OAuth認証用ヘッダ作成・付加処理
486
487                 /// <summary>
488                 /// 初期化。各種トークンの設定とユーザー識別情報設定
489                 /// </summary>
490                 /// <param name="consumerKey">コンシューマー鍵</param>
491                 /// <param name="consumerSecret">コンシューマー秘密鍵</param>
492                 /// <param name="accessToken">アクセストークン</param>
493                 /// <param name="accessTokenSecret">アクセストークン秘密鍵</param>
494                 /// <param name="userIdentifier">アクセストークン取得時に得られるユーザー識別情報。不要なら空文字列</param>
495                 public void Initialize( string consumerKey, string consumerSecret,
496                                         string accessToken, string accessTokenSecret,
497                                         string userIdentifier, string userIdIdentifier )
498                 {
499                         this.consumerKey = consumerKey;
500                         this.consumerSecret = consumerSecret;
501                         this.token = accessToken;
502                         this.tokenSecret = accessTokenSecret;
503                         this.userIdentKey = userIdentifier;
504                         this.userIdIdentKey = userIdIdentifier;
505                 }
506
507                 /// <summary>
508                 /// 初期化。各種トークンの設定とユーザー識別情報設定
509                 /// </summary>
510                 /// <param name="consumerKey">コンシューマー鍵</param>
511                 /// <param name="consumerSecret">コンシューマー秘密鍵</param>
512                 /// <param name="accessToken">アクセストークン</param>
513                 /// <param name="accessTokenSecret">アクセストークン秘密鍵</param>
514                 /// <param name="username">認証済みユーザー名</param>
515                 /// <param name="userIdentifier">アクセストークン取得時に得られるユーザー識別情報。不要なら空文字列</param>
516                 public void Initialize( string consumerKey, string consumerSecret,
517                                         string accessToken, string accessTokenSecret,
518                                         string username, long userId,
519                                         string userIdentifier, string userIdIdentifier )
520                 {
521                         this.Initialize( consumerKey, consumerSecret, accessToken, accessTokenSecret, userIdentifier, userIdIdentifier );
522                         this.authorizedUsername = username;
523                         this.authorizedUserId = userId;
524                 }
525
526                 /// <summary>
527                 /// アクセストークン
528                 /// </summary>
529                 public string AccessToken
530                 {
531                         get { return this.token; }
532                 }
533
534                 /// <summary>
535                 /// アクセストークン秘密鍵
536                 /// </summary>
537                 public string AccessTokenSecret
538                 {
539                         get { return this.tokenSecret; }
540                 }
541
542                 /// <summary>
543                 /// 認証済みユーザー名
544                 /// </summary>
545                 public string AuthUsername
546                 {
547                         get { return this.authorizedUsername; }
548                 }
549
550                 /// <summary>
551                 /// 認証済みユーザーId
552                 /// </summary>
553                 public long AuthUserId
554                 {
555                         get { return this.authorizedUserId; }
556                         set { this.authorizedUserId = value; }
557                 }
558         }
559 }