Пример #1
0
        /// <summary>GetClaims</summary>
        /// <param name="userName">string</param>
        /// <param name="roles">string</param>
        /// <param name="scopes">string</param>
        /// <param name="ipAddress">string</param>
        public static void GetClaims(out string userName, out string roles, out string scopes, out string ipAddress)
        {
            // MyHttpContext.Current.User.Identity側ではなく、Identities側に入っている。
            // Identityは認証ミドルウェアを使用する必要がある?(coreでjwtをどう処理するのか?)
            IEnumerable <Claim> claims = MyBaseAsyncApiController.GetRawClaims();

            if (claims == null)
            {
                // claims == null
                userName  = "******";
                roles     = "";
                scopes    = "";
                ipAddress = "";
            }
            else
            {
                // claims != null
                Claim claim = null;

                claim = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name);
                if (claim == null)
                {
                    userName = "******";
                }
                else
                {
                    userName = claim.Value;
                }

                claim = claims.FirstOrDefault(c => c.Type == ClaimTypes.Role);
                if (claim == null)
                {
                    roles = "";
                }
                else
                {
                    roles = claim.Value;
                }

                claim = claims.FirstOrDefault(c => c.Type == OAuth2AndOIDCConst.UrnScopesClaim);
                if (claim == null)
                {
                    scopes = "";
                }
                else
                {
                    scopes = claim.Value;
                }

                claim = claims.FirstOrDefault(c => c.Type == "IpAddress");
                if (claim == null)
                {
                    ipAddress = "";
                }
                else
                {
                    ipAddress = claim.Value;
                }
            }
        }
Пример #2
0
        /// <summary>
        /// アクション メソッドの呼び出し後に発生します。
        /// https://msdn.microsoft.com/ja-jp/library/dn573277.aspx
        /// </summary>
        /// <param name="actionExecutedContext">HttpActionExecutedContext</param>
        /// <param name="cancellationToken">CancellationToken</param>
        public override async Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
        {
            // Calling base class method.
            await base.OnActionExecutedAsync(actionExecutedContext, cancellationToken);

            // 性能測定終了
            this.perfRec.EndsPerformanceRecord();

            // ------------
            // メッセージ部
            // ------------
            // ユーザ名, IPアドレス,
            // レイヤ, 画面名, コントロール名, 処理名
            // 処理時間(実行時間), 処理時間(CPU時間)
            // エラーメッセージID, エラーメッセージ等
            // ------------

            // Claimを取得する。
            string userName, roles, scopes, ipAddress;

            MyBaseAsyncApiController.GetClaims(out userName, out roles, out scopes, out ipAddress);

            string strLogMessage =
                "," + userName +  //this.UserInfo.UserName +
                "," + ipAddress + //this.UserInfo.IPAddress +
                "," + "<-----" +
                "," + this.ControllerName +
                "," + this.ActionName + "(OnActionExecuted)" +
                "," + perfRec.ExecTime +
                "," + perfRec.CpuTime;

            LogIF.InfoLog("ACCESS", strLogMessage);
        }
Пример #3
0
        /// <summary>GetClaims</summary>
        /// <param name="userName">string</param>
        /// <param name="roles">string</param>
        /// <param name="scopes">string</param>
        /// <param name="ipAddress">string</param>
        public static void GetClaims(out string userName, out string roles, out string scopes, out string ipAddress)
        {
            IEnumerable <Claim> claims = MyBaseAsyncApiController.GetRawClaims();

            if (claims == null)
            {
                // claims == null
                userName  = "******";
                roles     = "";
                scopes    = "";
                ipAddress = "";
            }
            else
            {
                // claims != null
                Claim claim = null;

                claim = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name);
                if (claim == null)
                {
                    userName = "******";
                }
                else
                {
                    userName = claim.Value;
                }

                claim = claims.FirstOrDefault(c => c.Type == ClaimTypes.Role);
                if (claim == null)
                {
                    roles = "";
                }
                else
                {
                    roles = claim.Value;
                }

                claim = claims.FirstOrDefault(c => c.Type == OAuth2AndOIDCConst.UrnScopesClaim);
                if (claim == null)
                {
                    scopes = "";
                }
                else
                {
                    scopes = claim.Value;
                }

                claim = claims.FirstOrDefault(c => c.Type == "IpAddress");
                if (claim == null)
                {
                    ipAddress = "";
                }
                else
                {
                    ipAddress = claim.Value;
                }
            }
        }
        /// <summary>GetClaims</summary>
        /// <param name="userName">string</param>
        /// <param name="roles">string</param>
        /// <param name="scopes">string</param>
        /// <param name="ipAddress">string</param>
        public static void GetClaims(out string userName, out string roles, out string scopes, out string ipAddress)
        {
            IEnumerable <Claim> claims = MyBaseAsyncApiController.GetRawClaims();

            userName  = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name).Value;
            roles     = claims.FirstOrDefault(c => c.Type == ClaimTypes.Role).Value;
            scopes    = claims.FirstOrDefault(c => c.Type == OAuth2AndOIDCConst.UrnScopesClaim).Value;
            ipAddress = claims.FirstOrDefault(c => c.Type == "IpAddress").Value;
        }
Пример #5
0
        /// <summary>GetClaims</summary>
        /// <param name="userName">string</param>
        /// <param name="roles">string</param>
        /// <param name="scopes">string</param>
        /// <param name="ipAddress">string</param>
        public static void GetClaims(out string userName, out string roles, out string scopes, out string ipAddress)
        {
            // MyHttpContext.Current.User.Identity側ではなく、Identities側に入っている。
            // Identityは認証ミドルウェアを使用する必要がある?(coreでjwtをどう処理するのか?)
            IEnumerable <Claim> claims = MyBaseAsyncApiController.GetRawClaims();

            userName  = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name).Value;
            roles     = claims.FirstOrDefault(c => c.Type == ClaimTypes.Role).Value;
            scopes    = claims.FirstOrDefault(c => c.Type == OAuth2AndOIDCConst.UrnScopesClaim).Value;
            ipAddress = claims.FirstOrDefault(c => c.Type == "IpAddress").Value;
        }
Пример #6
0
        /// <summary>GetRawClaims</summary>
        /// <returns>IEnumerable(Claim)</returns>
        public static IEnumerable <Claim> GetRawClaims()
        {
            ClaimsIdentity claimsIdentity = MyBaseAsyncApiController.GetClaimsIdentity();

            if (claimsIdentity == null)
            {
                return(null);
            }
            else
            {
                return(claimsIdentity.Claims);
            }
        }
Пример #7
0
        /// <summary>
        /// アクション メソッドの呼び出し前に発生します。
        /// https://msdn.microsoft.com/ja-jp/library/dn573278.aspx
        /// </summary>
        /// <param name="actionContext">HttpActionContext</param>
        /// <param name="cancellationToken">CancellationToken</param>
        public override async Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
        {
            // Controller・Action名を取得する。
            this.GetControllerAndActionName(actionContext);

            // Claimを取得する。
            string userName, roles, scopes, ipAddress;

            MyBaseAsyncApiController.GetClaims(out userName, out roles, out scopes, out ipAddress);

            // 権限チェック ------------------------------------------------
            // ・・・
            // -------------------------------------------------------------

            // 閉塞チェック ------------------------------------------------
            // ・・・
            // -------------------------------------------------------------

            // 性能測定開始
            this.perfRec = new PerformanceRecorder();
            this.perfRec.StartsPerformanceRecord();

            // Calling base class method.
            await base.OnActionExecutingAsync(actionContext, cancellationToken);

            // ------------
            // メッセージ部
            // ------------
            // ユーザ名, IPアドレス,
            // レイヤ, 画面名, コントロール名, 処理名
            // 処理時間(実行時間), 処理時間(CPU時間)
            // エラーメッセージID, エラーメッセージ等
            // ------------

            string strLogMessage =
                "," + userName +  //this.UserInfo.UserName +
                "," + ipAddress + //this.UserInfo.IPAddress +
                "," + "----->" +
                "," + this.ControllerName +
                "," + this.ActionName + "(OnActionExecuting)";

            LogIF.InfoLog("ACCESS", strLogMessage);
        }
Пример #8
0
        /// <summary>エラーログの出力</summary>
        /// <param name="exceptionContext">HttpActionExecutedContext</param>
        private void OutputErrorLog(ExceptionContext exceptionContext)
        {
            // 非同期ControllerのInnerException対策(底のExceptionを取得する)。
            Exception ex = exceptionContext.Exception;
            Exception bottomException = ex;

            while (bottomException.InnerException != null)
            {
                bottomException = bottomException.InnerException;
            }

            // ------------
            // メッセージ部
            // ------------
            // ユーザ名, IPアドレス,
            // レイヤ, 画面名, コントロール名, 処理名
            // 処理時間(実行時間), 処理時間(CPU時間)
            // エラーメッセージID, エラーメッセージ等
            // ------------

            // Claimを取得する。
            string userName, roles, scopes, ipAddress;

            MyBaseAsyncApiController.GetClaims(out userName, out roles, out scopes, out ipAddress);

            string strLogMessage =
                "," + userName +  // (this.UserInfo != null ? this.UserInfo.UserName : "******") +
                "," + ipAddress + //(this.UserInfo != null ? this.UserInfo.IPAddress : "null") +
                "," + "<-----" +
                "," + this.ControllerName +
                "," + this.ActionName + "(ExecuteExceptionFilterAsync)" +
                "," + //this.perfRec.ExecTime +
                "," + //this.perfRec.CpuTime +
                "," + GetExceptionMessageID(bottomException) +
                "," + bottomException.Message + "\r\n" +
                "," + bottomException.StackTrace + "\r\n" +
                "," + ex.ToString(); // Exception.ToString()はRootのExceptionに対して行なう。

            LogIF.ErrorLog("ACCESS", strLogMessage);
        }
Пример #9
0
        /// <summary>ユーザ情報を取得する</summary>
        /// <param name="authorizationContext">AuthorizationFilterContext</param>
        /// <remarks>awaitするメソッドを追加して呼ぶ可能性も高いのでasyncを付与</remarks>
        private async Task GetUserInfoAsync(AuthorizationFilterContext authorizationContext)
        {
            // Authorization: <type> <credentials>
            if (this.HttpAuthHeader == EnumHttpAuthHeader.None)
            {
                // 認証なし
                return;
            }
            else if (this.HttpAuthHeader.HasFlag(EnumHttpAuthHeader.Basic))
            {
                // Basic認証の認証アルゴリズムを追加
                // Authorization: Basic XXXXXXXXXX
                return;
            }
            else if (this.HttpAuthHeader.HasFlag(EnumHttpAuthHeader.Bearer))
            {
                // Bearer認証の認証アルゴリズムを追加 --------------------------
                // Authorization: Bearer XXXXXXXXXX
                // JWTアサーションを処理し、認証、UserInfoを生成するなど。
                // -------------------------------------------------------------
                List <Claim> claims = null;

                if (authorizationContext.HttpContext.Request.Headers != null)
                {
                    StringValues authHeaders = "";

                    try
                    {
                        if (authorizationContext.HttpContext.Request.Headers.TryGetValue("Authorization", out authHeaders))
                        {
                            string access_token = authHeaders[0].Split(' ')[1];

                            string        sub    = "";
                            List <string> roles  = null;
                            List <string> scopes = null;
                            JObject       jobj   = null;

                            if (AccessToken.Verify(access_token, out sub, out roles, out scopes, out jobj))
                            {
                                // ActionFilterAttributeとApiController間の情報共有はcontext.Principalを使用する。
                                // ★ 必要であれば、他の業務共通引継ぎ情報などをロードする。
                                claims = new List <Claim>()
                                {
                                    new Claim(ClaimTypes.Name, sub),
                                    new Claim(ClaimTypes.Role, string.Join(",", roles)),
                                    new Claim(OAuth2AndOIDCConst.UrnScopesClaim, string.Join(",", scopes)),
                                    new Claim(OAuth2AndOIDCConst.UrnAudienceClaim, (string)jobj[OAuth2AndOIDCConst.aud]),
                                    new Claim("IpAddress", MyBaseAsyncApiController.GetClientIpAddress())
                                };

                                // ClaimsPrincipalを設定
                                MyHttpContext.Current.User = new ClaimsPrincipal(new ClaimsIdentity(claims, "Token"));

                                return;
                            }
                            else
                            {
                                // JWTの内容検証に失敗
                            }
                        }
                        else
                        {
                            // Authorization HeaderがBearerでない。
                        }
                    }
                    catch
                    {
                        // 例外発生 ≒ 未認証扱い。
                    }
                }
                else
                {
                    // Authorization Headerが存在しない。
                }

                #region 未認証状態の場合の扱い

                if (this.HttpAuthHeader.HasFlag(EnumHttpAuthHeader.None))
                {
                    // 未認証状態のclaimsを作成格納
                    claims = new List <Claim>()
                    {
                        new Claim(ClaimTypes.Name, "未認証"),
                        new Claim(ClaimTypes.Role, ""),
                        new Claim(OAuth2AndOIDCConst.UrnScopesClaim, ""),
                        new Claim(OAuth2AndOIDCConst.UrnAudienceClaim, ""),
                        new Claim("IpAddress", MyBaseAsyncApiController.GetClientIpAddress())
                    };

                    MyHttpContext.Current.User.AddIdentity(new ClaimsIdentity(claims, "Token"));
                }
                else
                {
                    // 認証エラーを返す。
                    // ASP.NET Core MVCで403エラーをクライアントへ返す - Living Absurd World
                    // https://blog.hmatoba.net/Article/144
                    authorizationContext.Result = new UnauthorizedResult();
                }

                return;

                #endregion
            }
        }
Пример #10
0
        /// <summary>
        /// アクション メソッドの呼び出し前に発生します(netcore)。
        /// https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.aspnetcore.mvc.filters.actionfilterattribute.onactionexecutionasync
        /// </summary>
        /// <param name="context">HttpActionContext</param>
        /// <param name="next">ActionExecutionDelegate</param>
        public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            #region OnActionExecutingAsyncから移行

            // Controller・Action名を取得する。
            this.GetControllerAndActionName(context);

            // Claimを取得する。
            string userName, roles, scopes, ipAddress;
            MyBaseAsyncApiController.GetClaims(out userName, out roles, out scopes, out ipAddress);

            // 権限チェック ------------------------------------------------
            // ・・・
            // -------------------------------------------------------------

            // 閉塞チェック ------------------------------------------------
            // ・・・
            // -------------------------------------------------------------

            // 性能測定開始
            this.perfRec = new PerformanceRecorder();
            this.perfRec.StartsPerformanceRecord();

            // ------------
            // メッセージ部
            // ------------
            // ユーザ名, IPアドレス,
            // レイヤ, 画面名, コントロール名, 処理名
            // 処理時間(実行時間), 処理時間(CPU時間)
            // エラーメッセージID, エラーメッセージ等
            // ------------

            string strLogMessage =
                "," + userName +  //this.UserInfo.UserName +
                "," + ipAddress + //this.UserInfo.IPAddress +
                "," + "----->" +
                "," + this.ControllerName +
                "," + this.ActionName + "(OnActionExecuting)";

            LogIF.InfoLog("ACCESS", strLogMessage);

            // 性能測定終了
            this.perfRec.EndsPerformanceRecord();

            #endregion

            await base.OnActionExecutionAsync(context, next);

            #region OnActionExecutedAsyncから移行

            // ------------
            // メッセージ部
            // ------------
            // ユーザ名, IPアドレス,
            // レイヤ, 画面名, コントロール名, 処理名
            // 処理時間(実行時間), 処理時間(CPU時間)
            // エラーメッセージID, エラーメッセージ等
            // -----------

            strLogMessage =
                "," + userName +  //this.UserInfo.UserName +
                "," + ipAddress + //this.UserInfo.IPAddress +
                "," + "<-----" +
                "," + this.ControllerName +
                "," + this.ActionName + "(OnActionExecuted)" +
                "," + perfRec.ExecTime +
                "," + perfRec.CpuTime;

            LogIF.InfoLog("ACCESS", strLogMessage);

            #endregion
        }
Пример #11
0
        /// <summary>ユーザ情報を取得する</summary>
        /// <param name="authenticationContext">HttpAuthenticationContext</param>
        private async Task GetUserInfoAsync(HttpAuthenticationContext authenticationContext)
        {
            // Authorization: <type> <credentials>
            if (this.HttpAuthHeader == EnumHttpAuthHeader.None)
            {
                // 認証なし
                return;
            }
            else if (this.HttpAuthHeader.HasFlag(EnumHttpAuthHeader.Basic))
            {
                // Basic認証の認証アルゴリズムを追加
                // Authorization: Basic XXXXXXXXXX
                return;
            }
            else if (this.HttpAuthHeader.HasFlag(EnumHttpAuthHeader.Bearer))
            {
                // Bearer認証の認証アルゴリズムを追加 --------------------------
                // Authorization: Bearer XXXXXXXXXX
                // JWTアサーションを処理し、認証、UserInfoを生成するなど。
                // -------------------------------------------------------------
                List <Claim> claims = null;

                if (authenticationContext.Request.Headers.Authorization != null)
                {
                    try
                    {
                        if (authenticationContext.Request.Headers.Authorization.Scheme.ToLower() == "bearer")
                        {
                            string access_token = authenticationContext.Request.Headers.Authorization.Parameter;

                            string        sub    = "";
                            List <string> roles  = null;
                            List <string> scopes = null;
                            JObject       jobj   = null;

                            if (AccessToken.Verify(access_token, out sub, out roles, out scopes, out jobj))
                            {
                                // ActionFilterAttributeとApiController間の情報共有はcontext.Principalを使用する。
                                // ★ 必要であれば、他の業務共通引継ぎ情報などをロードする。
                                claims = new List <Claim>()
                                {
                                    new Claim(ClaimTypes.Name, sub),
                                    new Claim(ClaimTypes.Role, string.Join(",", roles)),
                                    new Claim(OAuth2AndOIDCConst.UrnScopesClaim, string.Join(",", scopes)),
                                    new Claim(OAuth2AndOIDCConst.UrnAudienceClaim, (string)jobj[OAuth2AndOIDCConst.aud]),
                                    new Claim("IpAddress", MyBaseAsyncApiController.GetClientIpAddress(authenticationContext.Request))
                                };

                                // The request message contains valid credential.
                                authenticationContext.Principal = new ClaimsPrincipal(
                                    new List <ClaimsIdentity> {
                                    new ClaimsIdentity(claims, "Token")
                                });

                                return;
                            }
                            else
                            {
                                // JWTの内容検証に失敗
                            }
                        }
                        else
                        {
                            // Authorization HeaderがBearerでない。
                        }
                    }
                    catch
                    {
                        // 例外発生 ≒ 未認証扱い。
                    }
                }
                else
                {
                    // Authorization Headerが存在しない。
                }

                #region 未認証状態の場合の扱い

                if (this.HttpAuthHeader.HasFlag(EnumHttpAuthHeader.None))
                {
                    // 未認証状態のclaimsを作成格納
                    claims = new List <Claim>()
                    {
                        new Claim(ClaimTypes.Name, "未認証"),
                        new Claim(ClaimTypes.Role, ""),
                        new Claim(OAuth2AndOIDCConst.UrnScopesClaim, ""),
                        new Claim(OAuth2AndOIDCConst.UrnAudienceClaim, ""),
                        new Claim("IpAddress", MyBaseAsyncApiController.GetClientIpAddress(authenticationContext.Request))
                    };

                    authenticationContext.Principal = new ClaimsPrincipal(new List <ClaimsIdentity> {
                        new ClaimsIdentity(claims, "Token")
                    });
                }
                else
                {
                    // 認証エラーを返す。
                    // ASP.NET Web API 2 | Microsoft Docs
                    // https://docs.microsoft.com/ja-jp/aspnet/web-api/overview/security/authentication-filters
                    authenticationContext.ErrorResult = new AuthenticationFailureResult(
                        authenticationContext.Request, "Bearer Credentials is invalid.");
                }

                return;

                #endregion
            }
        }
Пример #12
0
 /// <summary>GetRawClaims</summary>
 /// <returns>IEnumerable(Claim)</returns>
 public static IEnumerable <Claim> GetRawClaims()
 {
     return(MyBaseAsyncApiController.GetClaimsIdentity().Claims);
 }
Пример #13
0
        /// <summary>ユーザ情報を取得する</summary>
        /// <param name="authorizationContext">AuthorizationFilterContext</param>
        /// <remarks>awaitするメソッドを追加して呼ぶ可能性も高いのでasyncを付与</remarks>
        private async Task GetUserInfoAsync(AuthorizationFilterContext authorizationContext)
        {
            // カスタム認証処理 --------------------------------------------
            // Authorization: Bearer ヘッダから
            // JWTアサーションを処理し、認証、UserInfoを生成するなど。
            // -------------------------------------------------------------
            List <Claim> claims = null;

            if (authorizationContext.HttpContext.Request.Headers != null)
            {
                StringValues authHeaders = "";

                if (authorizationContext.HttpContext.Request.Headers.TryGetValue("Authorization", out authHeaders))
                {
                    string access_token = authHeaders[0].Split(' ')[1];

                    string        sub    = "";
                    List <string> roles  = null;
                    List <string> scopes = null;
                    JObject       jobj   = null;

                    if (AccessToken.Verify(access_token, out sub, out roles, out scopes, out jobj))
                    {
                        // ActionFilterAttributeとApiController間の情報共有はcontext.Principalを使用する。
                        // ★ 必要であれば、他の業務共通引継ぎ情報などをロードする。
                        claims = new List <Claim>()
                        {
                            new Claim(ClaimTypes.Name, sub),
                            new Claim(ClaimTypes.Role, string.Join(",", roles)),
                            new Claim(OAuth2AndOIDCConst.UrnScopesClaim, string.Join(",", scopes)),
                            new Claim(OAuth2AndOIDCConst.UrnAudienceClaim, (string)jobj[OAuth2AndOIDCConst.aud]),
                            new Claim("IpAddress", MyBaseAsyncApiController.GetClientIpAddress())
                        };

                        // ClaimsPrincipalを設定
                        MyHttpContext.Current.User = new ClaimsPrincipal(new ClaimsIdentity(claims, "Token"));

                        return;
                    }
                    else
                    {
                        // JWTの内容検証に失敗
                    }
                }
                else
                {
                    // Authorization HeaderがBearerでない。
                }
            }
            else
            {
                // Authorization Headerが存在しない。
            }

            #region 未認証状態の場合の扱い

            // The request message contains invalid credential
            //context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], context.Request);

            // 未認証状態のclaimsを作成格納
            claims = new List <Claim>()
            {
                new Claim(ClaimTypes.Name, "未認証"),
                new Claim(ClaimTypes.Role, ""),
                new Claim(OAuth2AndOIDCConst.UrnScopesClaim, ""),
                new Claim(OAuth2AndOIDCConst.UrnAudienceClaim, ""),
                new Claim("IpAddress", MyBaseAsyncApiController.GetClientIpAddress())
            };

            // The request message contains valid credential.
            MyHttpContext.Current.User.AddIdentity(new ClaimsIdentity(claims, "Token"));

            return;

            #endregion
        }
Пример #14
0
        /// <summary>ユーザ情報を取得する</summary>
        /// <param name="authenticationContext">HttpAuthenticationContext</param>
        private async Task GetUserInfoAsync(HttpAuthenticationContext authenticationContext)
        {
            // カスタム認証処理 --------------------------------------------
            // Authorization: Bearer ヘッダから
            // JWTアサーションを処理し、認証、UserInfoを生成するなど。
            // -------------------------------------------------------------
            List <Claim> claims = null;

            if (authenticationContext.Request.Headers.Authorization.Scheme.ToLower() == "bearer")
            {
                string access_token = authenticationContext.Request.Headers.Authorization.Parameter;

                string        sub    = "";
                List <string> roles  = null;
                List <string> scopes = null;
                JObject       jobj   = null;

                if (JwtToken.Verify(access_token, out sub, out roles, out scopes, out jobj))
                {
                    // ActionFilterAttributeとApiController間の情報共有はcontext.Principalを使用する。
                    // ★ 必要であれば、他の業務共通引継ぎ情報などをロードする。
                    claims = new List <Claim>()
                    {
                        new Claim(ClaimTypes.Name, sub),
                        new Claim(ClaimTypes.Role, string.Join(",", roles)),
                        new Claim("Scopes", string.Join(",", scopes)),
                        new Claim("IpAddress", MyBaseAsyncApiController.GetClientIpAddress(authenticationContext.Request))
                    };

                    // The request message contains valid credential
                    authenticationContext.Principal = new ClaimsPrincipal(new List <ClaimsIdentity> {
                        new ClaimsIdentity(claims, "Token")
                    });
                    return;
                }
                else
                {
                    // JWTの内容検証に失敗
                }
            }
            else
            {
                // Authorization: Bearer Headerが存在しない。
            }

            // 未認証状態
            // The request message contains invalid credential
            //context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], context.Request);

            claims = new List <Claim>()
            {
                new Claim(ClaimTypes.Name, "未認証"),
                new Claim(ClaimTypes.Role, ""),
                new Claim("Scopes", ""),
                new Claim("IpAddress", MyBaseAsyncApiController.GetClientIpAddress(authenticationContext.Request))
            };

            authenticationContext.Principal = new ClaimsPrincipal(new List <ClaimsIdentity> {
                new ClaimsIdentity(claims, "Token")
            });
            return;
        }