예제 #1
0
        /// <summary>RS256のJWT検証メソッド</summary>
        /// <param name="jwtString">JWTの文字列表現</param>
        /// <returns>署名の検証結果</returns>
        public override bool Verify(string jwtString)
        {
            string[] temp = jwtString.Split('.');

            // 検証
            Header headerObject = (Header)JsonConvert.DeserializeObject(
                CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(temp[0]), CustomEncode.UTF_8), typeof(Header));

            if (headerObject.alg == "RS256" && headerObject.typ == "JWT")
            {
                byte[] data = CustomEncode.StringToByte(temp[0] + "." + temp[1], CustomEncode.UTF_8);
                byte[] sign = CustomEncode.FromBase64UrlString(temp[2]);
                return(this._cs.Verify(data, sign));
            }
            else
            {
                return(false);
            }
        }
예제 #2
0
파일: Form1.cs 프로젝트: ukayare/OpenTouryo
 /// <summary>共通鍵・復号化</summary>
 private void button5_Click(object sender, EventArgs e)
 {
     if (this.rbnASCString.Checked)
     {
         // String
         this.txtASCString.Text =
             ASymmetricCryptography.DecryptString(this.txtASCCode.Text, this.txtASCPublic.Text);
     }
     else
     {
         // Bytes
         this.txtASCString.Text =
             CustomEncode.ByteToString(
                 ASymmetricCryptography.DecryptBytes(
                     CustomEncode.FormHexString(this.txtASCCode.Text),
                     this.txtASCPublic.Text),
                 CustomEncode.UTF_8);
     }
 }
예제 #3
0
        /// <summary>ES256のJWS検証メソッド</summary>
        /// <param name="jwtString">JWSの文字列表現</param>
        /// <returns>署名の検証結果</returns>
        public override bool Verify(string jwtString)
        {
            string[] temp = jwtString.Split('.');

            // 検証
            JWS_Header headerObject = (JWS_Header)JsonConvert.DeserializeObject(
                CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(temp[0]), CustomEncode.UTF_8), typeof(JWS_Header));

            if (headerObject.alg.ToUpper() == JwtConst.ES256 && headerObject.typ.ToUpper() == JwtConst.JWT)
            {
                byte[] data = CustomEncode.StringToByte(temp[0] + "." + temp[1], CustomEncode.UTF_8);
                byte[] sign = CustomEncode.FromBase64UrlString(temp[2]);
                return(this.Verify2(data, sign)); // 派生を呼ぶ
            }
            else
            {
                return(false);
            }
        }
예제 #4
0
        /// <summary>JWT生成</summary>
        private void btnJWTSign_Click(object sender, EventArgs e)
        {
            if (rbnJWTHS256.Checked)
            {
                // HS256
                string    password = GetPassword.Generate(20, 10);
                JWT_HS256 jwtHS256 = new JWT_HS256(CustomEncode.StringToByte(password, CustomEncode.UTF_8));

                // 生成
                string jwt = jwtHS256.Create(this.txtJWTPayload.Text);

                // 出力
                this.txtJWTKey.Text  = password;
                this.txtJWTJWK.Text  = jwtHS256.JWK;
                this.txtJWTSign.Text = jwt;

                // 改竄可能なフィールドに出力
                string[] temp = jwt.Split('.');
                this.txtJWTHeader.Text = CustomEncode.ByteToString(
                    CustomEncode.FromBase64UrlString(temp[0]), CustomEncode.UTF_8);
                this.txtJWTPayload.Text = CustomEncode.ByteToString(
                    CustomEncode.FromBase64UrlString(temp[1]), CustomEncode.UTF_8);
            }
            else
            {
                // RS256 (X509Cer)
                JWT_RS256 jwtRS256 = new JWT_RS256(this.CertificateFilePath_pfx, this.CertificateFilePassword);

                // 生成
                string jwt = jwtRS256.Create(this.txtJWTPayload.Text);

                // 出力
                this.txtJWTSign.Text = jwt;

                // 改竄可能なフィールドに出力
                string[] temp = jwt.Split('.');
                this.txtJWTHeader.Text = CustomEncode.ByteToString(
                    CustomEncode.FromBase64UrlString(temp[0]), CustomEncode.UTF_8);
                this.txtJWTPayload.Text = CustomEncode.ByteToString(
                    CustomEncode.FromBase64UrlString(temp[1]), CustomEncode.UTF_8);
            }
        }
예제 #5
0
        /// <summary>VerifyResult</summary>
        /// <param name="testId">string</param>
        /// <param name="token">string</param>
        /// <param name="key">object</param>
        private static void VerifyResult(string testId, string token, object key)
        {
            Program.MyWriteLine(testId + token);

            string[] aryStr = token.Split('.');

            Program.MyWriteLine("JWT Header: " + CustomEncode.ByteToString(
                                    CustomEncode.FromBase64UrlString(aryStr[0]), CustomEncode.UTF_8));

            if (3 < aryStr.Length)
            {
                // JWE
                Program.MyWriteLine("- JWE Encrypted Key: " + aryStr[1]);
                Program.MyWriteLine("- JWE Initialization Vector: " + aryStr[2]);
                Program.MyWriteLine("- JWE Ciphertext: " + aryStr[3]);
                Program.MyWriteLine("- JWE Authentication Tag: " + aryStr[4]);
            }

            Program.MyWriteLine("Decoded: " + JWT.Decode(token, key));
        }
예제 #6
0
        /// <summary>パスワードを比較して認証する。</summary>
        /// <param name="rawPassword">Password entered by the user.</param>
        /// <param name="saltedPassword">Salted and hashed password.</param>
        /// <param name="eha">ハッシュ・アルゴリズム列挙型</param>
        /// <returns>
        /// true:パスワードは一致した。
        /// false:パスワードは一致しない。
        /// </returns>
        public static bool EqualSaltedPassword(string rawPassword, string saltedPassword, EnumHashAlgorithm eha)
        {
            // ソルト部分を取得
            string[] temp           = saltedPassword.Split('.');
            string   salt           = CustomEncode.ByteToString(CustomEncode.FromBase64String(temp[0]), CustomEncode.UTF_8);
            int      stretchCount   = int.Parse(CustomEncode.ByteToString(CustomEncode.FromBase64String(temp[1]), CustomEncode.UTF_8));
            string   hashedPassword = CustomEncode.ByteToString(CustomEncode.FromBase64String(temp[2]), CustomEncode.UTF_8);

            // 引数のsaltedPasswordと、rawPasswordから自作したsaltedPasswordを比較
            if (hashedPassword == GetHash.GetHashString(salt + rawPassword, eha, stretchCount))
            {
                // 一致した。
                return(true);
            }
            else
            {
                // 一致しなかった。
                return(false);
            }
        }
예제 #7
0
        public static void ByteToStringTest(byte[] abyt, int codePageNum)
        {
            try
            {
                // Convert to string using the components touryo.
                string str = CustomEncode.ByteToString(abyt, codePageNum);

                // Convert to byte using the components touryo.
                byte[] byteValue = CustomEncode.StringToByte(str, codePageNum);

                Assert.AreNotSame(abyt, str);
                //Check whether it is converted into the original byte.
                Assert.AreEqual(abyt, byteValue);
            }
            catch (Exception ex)
            {
                // Print a stack trace when an exception occurs.
                Console.WriteLine(ex.StackTrace);
                throw;
            }
        }
예제 #8
0
        /// <summary>パスワードを比較して認証する。</summary>
        /// <param name="rawPassword">Password entered by the user.</param>
        /// <param name="saltedPassword">Salted and hashed password.</param>
        /// <param name="ekha">ハッシュ・アルゴリズム列挙型</param>
        /// <returns>
        /// true:パスワードは一致した。
        /// false:パスワードは一致しない。
        /// </returns>
        public static bool EqualSaltedPassword(string rawPassword, string saltedPassword, EnumKeyedHashAlgorithm ekha)
        {
            // ソルト部分を取得
            string[] temp = saltedPassword.Split('.');

            // key
            string key = CustomEncode.ByteToString(CustomEncode.FromBase64String(temp[0]), CustomEncode.UTF_8);

            // saltByte
            byte[] saltByte = CustomEncode.FromBase64String(temp[1]);

            // salt
            string salt = CustomEncode.ByteToString(saltByte, CustomEncode.UTF_8);

            // stretchCount
            int stretchCount = int.Parse(CustomEncode.ByteToString(CustomEncode.FromBase64String(temp[2]), CustomEncode.UTF_8));

            // Salted and hashed password
            string hashedPassword = temp[3];

            // KeyedHashのキーを生成する。
            Rfc2898DeriveBytes passwordKey = new Rfc2898DeriveBytes(key, saltByte, stretchCount);

            // 引数のsaltedPasswordと、rawPasswordから自作したsaltedPasswordを比較
            string compare = CustomEncode.ToBase64String(
                GetPasswordHashV2.GetKeyedHashBytes(
                    CustomEncode.StringToByte(salt + rawPassword, CustomEncode.UTF_8),
                    ekha, passwordKey.GetBytes(24)));

            if (hashedPassword == compare)
            {
                // 一致した。
                return(true);
            }
            else
            {
                // 一致しなかった。
                return(false);
            }
        }
예제 #9
0
        /// <summary>RS256のJWT検証メソッド</summary>
        /// <param name="jwtString">JWTの文字列表現</param>
        /// <returns>署名の検証結果</returns>
        public override bool Verify(string jwtString)
        {
            string[] temp = jwtString.Split('.');

            // 検証
            Header headerObject = (Header)JsonConvert.DeserializeObject(
                CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(temp[0]), CustomEncode.UTF_8), typeof(Header));

            if (headerObject.alg == "HS256" && headerObject.typ == "JWT")
            {
                byte[] data = CustomEncode.StringToByte(temp[0] + "." + temp[1], CustomEncode.UTF_8);
                byte[] sign = CustomEncode.FromBase64UrlString(temp[2]);

                HMACSHA256 sa = new HMACSHA256(this.Key);

                return(CustomEncode.ToBase64UrlString(sign)
                       == CustomEncode.ToBase64UrlString(sa.ComputeHash(data)));
            }
            else
            {
                return(false);
            }
        }
        public async Task <ActionResult> TestJWTBearerTokenFlow()
        {
            // Token2エンドポイントにアクセス
            string aud = ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI
                         + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint2;

            // ClientNameから、client_id(iss)を取得。
            string iss = "";

            if (User.Identity.IsAuthenticated)
            {
                // User Accountの場合、
                iss = OAuth2Helper.GetInstance().GetClientIdByName(User.Identity.Name);
            }
            else
            {
                // Client Accountの場合、
                iss = OAuth2Helper.GetInstance().GetClientIdByName("TestClient");
            }

            // テストなので秘密鍵は共通とする。
            string privateKey = OAuth2AndOIDCParams.OAuth2JwtAssertionPrivatekey;

            privateKey = CustomEncode.ByteToString(CustomEncode.FromBase64String(privateKey), CustomEncode.us_ascii);

            string response = await OAuth2Helper.GetInstance()
                              .JwtBearerTokenFlowAsync(new Uri(
                                                           ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI
                                                           + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint2),
                                                       JwtAssertion.CreateJwtBearerTokenFlowAssertion(
                                                           iss, aud, new TimeSpan(0, 0, 30), ASPNETIdentityConst.StandardScopes, privateKey));

            ViewBag.Response    = response;
            ViewBag.AccessToken = ((JObject)JsonConvert.DeserializeObject(response))[OAuth2AndOIDCConst.AccessToken];

            return(View("OAuth2ClientAuthenticationFlow"));
        }
예제 #11
0
        /// <summary>GetCredentials</summary>
        /// <param name="authHeader">string</param>
        /// <param name="credentials">string[]</param>
        /// <returns>AuthenticationScheme</returns>
        public static string GetCredentials(string authHeader, out string[] credentials)
        {
            if (!string.IsNullOrEmpty(authHeader))
            {
                string[] temp = authHeader.Split(' ');

                if (temp[0] == OAuth2AndOIDCConst.Basic)
                {
                    credentials = CustomEncode.ByteToString(
                        CustomEncode.FromBase64String(temp[1]), CustomEncode.us_ascii).Split(':');

                    return(OAuth2AndOIDCConst.Basic);
                }
                else if (temp[0] == OAuth2AndOIDCConst.Bearer)
                {
                    credentials = new string[] { temp[1] };

                    return(OAuth2AndOIDCConst.Bearer);
                }
            }

            credentials = new string[] { };
            return("");
        }
예제 #12
0
        /// <summary>HSXXXのJWS検証メソッド</summary>
        /// <param name="jwtString">JWSの文字列表現</param>
        /// <returns>署名の検証結果</returns>
        public override bool Verify(string jwtString)
        {
            string[] temp = jwtString.Split('.');

            // 検証
            JWS_Header headerObject = (JWS_Header)JsonConvert.DeserializeObject(
                CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(temp[0]), CustomEncode.UTF_8), typeof(JWS_Header));

            if (headerObject.alg.ToUpper() == this.JwtConstHSnnn &&
                headerObject.typ.ToUpper() == JwtConst.JWT)
            {
                byte[] data = CustomEncode.StringToByte(temp[0] + "." + temp[1], CustomEncode.UTF_8);
                byte[] sign = CustomEncode.FromBase64UrlString(temp[2]);

                HMAC sa = this.CreateHMACSHA(this.Key);

                return(CustomEncode.ToBase64UrlString(sign)
                       == CustomEncode.ToBase64UrlString(sa.ComputeHash(data)));
            }
            else
            {
                return(false);
            }
        }
예제 #13
0
        /// <summary>汎用認証サイトの発行したJWT形式のTokenを検証する。</summary>
        /// <param name="jwtToken">JWT形式のToken</param>
        /// <param name="jwtPayload">
        /// JWS, JWS + JEWの場合があるのでペイロードを返す。
        /// </param>
        /// <returns>検証結果</returns>
        public static bool Verify(string jwtToken, out string jwtPayload)
        {
            jwtPayload = "";

            JWE jwe = null;
            JWS jws = null;

            // 復号化(JWEの場合)
            bool isJWE_FAPI2 = false;

            if (3 < jwtToken.Split('.').Length)
            {
                isJWE_FAPI2 = true;

                // ヘッダ
                JWE_Header jweHeader = JsonConvert.DeserializeObject <JWE_Header>(
                    CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(jwtToken.Split('.')[0]), CustomEncode.UTF_8));

                if (jweHeader.alg == JwtConst.RSA_OAEP)
                {
                    jwe = new JWE_RsaOaepAesGcm_X509(
                        CmnClientParams.RsaPfxFilePath,
                        CmnClientParams.RsaPfxPassword);
                }
                else if (jweHeader.alg == JwtConst.RSA1_5)
                {
                    jwe = new JWE_Rsa15A128CbcHS256_X509(
                        CmnClientParams.RsaPfxFilePath,
                        CmnClientParams.RsaPfxPassword);
                }
                else
                {
                    throw new NotSupportedException(string.Format(
                                                        "This jwe alg of {0} is not supported.", jweHeader.alg));
                }

                jwe.Decrypt(jwtToken, out jwtToken);
            }
            else
            {
                isJWE_FAPI2 = false;
            }

            // 検証
            // ヘッダ
            JWS_Header jwsHeader = JsonConvert.DeserializeObject <JWS_Header>(
                CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(jwtToken.Split('.')[0]), CustomEncode.UTF_8));

            if (jwsHeader.alg == JwtConst.ES256 && isJWE_FAPI2)
            {
            }                                                       // 正常
            else if (jwsHeader.alg == JwtConst.RS256 && !isJWE_FAPI2)
            {
            }                                                             // 正常
            else
            {
                throw new NotSupportedException("Unexpected combination of JWS and JWE.");
            }

            // 証明書を使用するか、Jwkを使用するか判定
            if (string.IsNullOrEmpty(jwsHeader.jku) ||
                string.IsNullOrEmpty(jwsHeader.kid))
            {
                // 旧バージョン(証明書を使用
                if (isJWE_FAPI2)
                {
#if NET45 || NET46
                    throw new NotSupportedException("FAPI2 is not supported in this dotnet version.");
#else
                    jws = new JWS_ES256_X509(CmnClientParams.EcdsaCerFilePath, "");
#endif
                }
                else
                {
                    jws = new JWS_RS256_X509(CmnClientParams.RsaCerFilePath, "");
                }
            }
            else
            {
                // 新バージョン(Jwkを使用
                if (string.IsNullOrEmpty(OAuth2AndOIDCParams.JwkSetFilePath))
                {
                    // jku(jwks_uri)使用のカバレッジ

                    // Client側
                    JObject jwkObject = JwkSetStore.GetInstance().GetJwkObject(jwsHeader.kid);

                    // チェック
                    if (jwkObject == null)
                    {
                        // 書込
                        jwkObject = JwkSetStore.GetInstance().SetJwkSetObject(jwsHeader.jku, jwsHeader.kid);
                    }

                    // チェック
                    if (jwkObject == null)
                    {
                        // 証明書を使用
                        if (isJWE_FAPI2)
                        {
#if NET45 || NET46
                            throw new NotSupportedException("FAPI2 is not supported in this dotnet version.");
#else
                            jws = new JWS_ES256_X509(CmnClientParams.EcdsaCerFilePath, "");
#endif
                        }
                        else
                        {
                            jws = new JWS_RS256_X509(CmnClientParams.RsaCerFilePath, "");
                        }
                    }
                    else
                    {
                        // Jwkを使用
                        if (isJWE_FAPI2)
                        {
#if NET45 || NET46
                            throw new NotSupportedException("FAPI2 is not supported in this dotnet version.");
#else
                            EccPublicKeyConverter epkc = new EccPublicKeyConverter();
                            jws = new JWS_ES256_Param(epkc.JwkToParam(jwkObject), false);
#endif
                        }
                        else
                        {
                            RsaPublicKeyConverter rpkc = new RsaPublicKeyConverter();
                            jws = new JWS_RS256_Param(rpkc.JwkToParam(jwkObject));
                        }
                    }
                }
                else
                {
                    // JwkSet使用のカバレッジ
                    // AuthZ側でClient側テストを行うためのカバレージ
                    JObject jwkObject = null;

                    if (ResourceLoader.Exists(OAuth2AndOIDCParams.JwkSetFilePath, false))
                    {
                        JwkSet jwkSet = JwkSet.LoadJwkSet(OAuth2AndOIDCParams.JwkSetFilePath);
                        jwkObject = JwkSet.GetJwkObject(jwkSet, jwsHeader.kid);
                    }

                    if (jwkObject == null)
                    {
                        // 証明書を使用
                        if (isJWE_FAPI2)
                        {
#if NET45 || NET46
                            throw new NotSupportedException("FAPI2 is not supported in this dotnet version.");
#else
                            jws = new JWS_ES256_X509(CmnClientParams.EcdsaCerFilePath, "");
#endif
                        }
                        else
                        {
                            jws = new JWS_RS256_X509(CmnClientParams.RsaCerFilePath, "");
                        }
                    }
                    else
                    {
                        // Jwkを使用
                        if (isJWE_FAPI2)
                        {
#if NET45 || NET46
                            throw new NotSupportedException("FAPI2 is not supported in this dotnet version.");
#else
                            EccPublicKeyConverter epkc = new EccPublicKeyConverter();
                            jws = new JWS_ES256_Param(epkc.JwkToParam(jwkObject), false);
#endif
                        }
                        else
                        {
                            RsaPublicKeyConverter rpkc = new RsaPublicKeyConverter();
                            jws = new JWS_RS256_Param(rpkc.JwkToParam(jwkObject));
                        }
                    }
                }
            }

            bool ret = jws.Verify(jwtToken);

            if (ret)
            {
                jwtPayload = CustomEncode.ByteToString(
                    CustomEncode.FromBase64UrlString(jwtToken.Split('.')[1]), CustomEncode.us_ascii);
            }

            return(ret);
        }
예제 #14
0
        //[Authorize]
        public Dictionary <string, string> OAuth2BearerToken2(FormDataCollection formData)
        {
            // 戻り値
            // ・正常
            Dictionary <string, string> ret = new Dictionary <string, string>();
            // ・異常
            Dictionary <string, string> err = new Dictionary <string, string>();

            // 変数
            string grant_type = formData[OAuth2AndOIDCConst.grant_type];
            string assertion  = formData[OAuth2AndOIDCConst.assertion];

            // クライアント認証
            if (grant_type == OAuth2AndOIDCConst.JwtBearerTokenFlowGrantType)
            {
                Dictionary <string, string> dic = JsonConvert.DeserializeObject <Dictionary <string, string> >(
                    CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(
                                                  assertion.Split('.')[1]), CustomEncode.us_ascii));

                string pubKey = OAuth2Helper.GetInstance().GetJwtAssertionPublickey(dic[OAuth2AndOIDCConst.iss]);
                pubKey = CustomEncode.ByteToString(CustomEncode.FromBase64String(pubKey), CustomEncode.us_ascii);

                if (!string.IsNullOrEmpty(pubKey))
                {
                    string  iss    = "";
                    string  aud    = "";
                    string  scopes = "";
                    JObject jobj   = null;

                    if (JwtAssertion.VerifyJwtBearerTokenFlowAssertion(assertion, out iss, out aud, out scopes, out jobj, pubKey))
                    {
                        // aud 検証
                        if (aud == ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI
                            + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint2)
                        {
                            // ここからは、JwtAssertionではなく、JwtTokenを作るので、属性設定に注意。
                            ClaimsIdentity identity = OAuth2Helper.AddClaim(
                                new ClaimsIdentity(OAuthDefaults.AuthenticationType), iss, "", scopes.Split(' '), "");

                            AuthenticationProperties prop = new AuthenticationProperties();
                            prop.IssuedUtc  = DateTimeOffset.UtcNow;
                            prop.ExpiresUtc = DateTimeOffset.Now.Add(ASPNETIdentityConfig.OAuth2AccessTokenExpireTimeSpanFromMinutes);

                            // token_type
                            ret.Add(OAuth2AndOIDCConst.token_type, OAuth2AndOIDCConst.Bearer.ToLower());

                            // access_token
                            AccessTokenFormatJwt verifier = new AccessTokenFormatJwt();
                            string access_token           = verifier.Protect(new AuthenticationTicket(identity, prop));
                            ret.Add(OAuth2AndOIDCConst.AccessToken, access_token);

                            // expires_in
                            jobj = (JObject)JsonConvert.DeserializeObject(
                                CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(
                                                              access_token.Split('.')[1]), CustomEncode.us_ascii));
                            ret.Add("expires_in", (long.Parse((string)jobj[OAuth2AndOIDCConst.exp]) - long.Parse((string)jobj[OAuth2AndOIDCConst.iat])).ToString());

                            // オペレーション・トレース・ログ出力
                            string clientName = OAuth2Helper.GetInstance().GetClientName(iss);
                            Logging.MyOperationTrace(string.Format(
                                                         "{0}({1}) passed the 'jwt bearer token flow' by {2}({3}).",
                                                         iss, clientName, iss, clientName));

                            return(ret); // 成功
                        }
                        else
                        {
                            // クライアント認証エラー(Credential(aud)不正
                            err.Add("error", "invalid_client");
                            err.Add("error_description", "Invalid credential");
                        }
                    }
                    else
                    {
                        // クライアント認証エラー(Credential(署名)不正
                        err.Add("error", "invalid_client");
                        err.Add("error_description", "Invalid credential");
                    }
                }
                else
                {
                    // クライアント認証エラー(Credential(iss or pubKey)不正
                    err.Add("error", "invalid_client");
                    err.Add("error_description", "Invalid credential");
                }
            }
            else
            {
                // grant_type パラメタ・エラー
                err.Add("error", "invalid_request");
                err.Add("error_description", "invalid grant_type");
            }

            return(err); // 失敗
        }
예제 #15
0
        //[Authorize]
        public Dictionary <string, string> IntrospectToken(FormDataCollection formData)
        {
            // 戻り値
            // ・正常
            Dictionary <string, string> ret = new Dictionary <string, string>();
            // ・異常
            Dictionary <string, string> err = new Dictionary <string, string>();

            // 変数
            string[] temp            = null;
            string   token           = formData[OAuth2AndOIDCConst.token];
            string   token_type_hint = formData[OAuth2AndOIDCConst.token_type_hint];

            // クライアント認証

            // クライアント識別子
            string authHeader = HttpContext.Current.Request.Headers[OAuth2AndOIDCConst.HttpHeader_Authorization];

            temp = authHeader.Split(' ');

            if (temp[0] == OAuth2AndOIDCConst.Basic)
            {
                temp = CustomEncode.ByteToString(
                    CustomEncode.FromBase64String(temp[1]), CustomEncode.us_ascii).Split(':');

                string clientId     = temp[0];
                string clientSecret = temp[1];

                if (!(string.IsNullOrEmpty(clientId) && string.IsNullOrEmpty(clientSecret)))
                {
                    // *.config or OAuth2Dataテーブルを参照してクライアント認証を行なう。
                    if (clientSecret == OAuth2Helper.GetInstance().GetClientSecret(clientId))
                    {
                        // 検証完了
                        AuthenticationTicket ticket = null;

                        if (token_type_hint == OAuth2AndOIDCConst.AccessToken)
                        {
                            // 検証
                            AccessTokenFormatJwt verifier = new AccessTokenFormatJwt();
                            ticket = verifier.Unprotect(token);

                            if (ticket == null)
                            {
                                // 検証失敗
                                // 検証エラー
                                err.Add("error", "invalid_request");
                                err.Add("error_description", "invalid token");
                            }
                            else
                            {
                                // 検証成功
                                // メタデータの返却
                                ret.Add("active", "true");
                                ret.Add(OAuth2AndOIDCConst.token_type, token_type_hint);

                                string scopes = "";
                                foreach (Claim claim in ticket.Identity.Claims)
                                {
                                    if (claim.Type.StartsWith(OAuth2AndOIDCConst.Claim_Base))
                                    {
                                        if (claim.Type == OAuth2AndOIDCConst.Claim_Scopes)
                                        {
                                            scopes += claim.Value + " ";
                                        }
                                        else
                                        {
                                            ret.Add(claim.Type.Substring(
                                                        OAuth2AndOIDCConst.Claim_Base.Length), claim.Value);
                                        }
                                    }
                                }
                                ret.Add(OAuth2AndOIDCConst.Claim_Scopes.Substring(
                                            OAuth2AndOIDCConst.Claim_Base.Length), scopes.Trim());

                                return(ret); // 成功
                            }
                        }
                        else if (token_type_hint == OAuth2AndOIDCConst.RefreshToken)
                        {
                            // refresh_token参照
                            ticket = RefreshTokenProvider.ReferDirectly(token);

                            if (ticket == null)
                            {
                                // 検証失敗
                                // 検証エラー
                                err.Add("error", "invalid_request");
                                err.Add("error_description", "invalid token");
                            }
                            else
                            {
                                // 検証成功
                                // メタデータの返却
                                ret.Add("active", "true");
                                ret.Add(OAuth2AndOIDCConst.token_type, token_type_hint);

                                string scopes = "";
                                foreach (Claim claim in ticket.Identity.Claims)
                                {
                                    if (claim.Type.StartsWith(OAuth2AndOIDCConst.Claim_Base))
                                    {
                                        if (claim.Type == OAuth2AndOIDCConst.Claim_Scopes)
                                        {
                                            scopes += claim.Value + " ";
                                        }
                                        else
                                        {
                                            ret.Add(claim.Type.Substring(
                                                        OAuth2AndOIDCConst.Claim_Base.Length), claim.Value);
                                        }
                                    }
                                }
                                ret.Add(OAuth2AndOIDCConst.Claim_Scopes.Substring(
                                            OAuth2AndOIDCConst.Claim_Base.Length), scopes.Trim());

                                return(ret); // 成功
                            }
                        }
                        else
                        {
                            // token_type_hint パラメタ・エラー
                            err.Add("error", "invalid_request");
                            err.Add("error_description", "invalid token_type_hint");
                        }
                    }
                    else
                    {
                        // クライアント認証エラー(Credential不正
                        err.Add("error", "invalid_client");
                        err.Add("error_description", "Invalid credential");
                    }
                }
                else
                {
                    // クライアント認証エラー(Credential不正
                    err.Add("error", "invalid_client");
                    err.Add("error_description", "Invalid credential");
                }
            }
            else
            {
                // クライアント認証エラー(ヘッダ不正
                err.Add("error", "invalid_request");
                err.Add("error_description", "Invalid authentication header");
            }

            return(err); // 失敗
        }
예제 #16
0
        //[Authorize]
        public Dictionary <string, string> RevokeToken(FormDataCollection formData)
        {
            // 戻り値(エラー)
            Dictionary <string, string> err = new Dictionary <string, string>();

            // 変数
            string[] temp            = null;
            string   token           = formData[OAuth2AndOIDCConst.token];
            string   token_type_hint = formData[OAuth2AndOIDCConst.token_type_hint];

            // クライアント認証

            // クライアント識別子
            string authHeader = HttpContext.Current.Request.Headers[OAuth2AndOIDCConst.HttpHeader_Authorization];

            temp = authHeader.Split(' ');

            if (temp[0] == OAuth2AndOIDCConst.Basic)
            {
                temp = CustomEncode.ByteToString(
                    CustomEncode.FromBase64String(temp[1]), CustomEncode.us_ascii).Split(':');

                string clientId     = temp[0];
                string clientSecret = temp[1];

                if (!(string.IsNullOrEmpty(clientId) && string.IsNullOrEmpty(clientSecret)))
                {
                    // *.config or OAuth2Dataテーブルを参照してクライアント認証を行なう。
                    if (clientSecret == OAuth2Helper.GetInstance().GetClientSecret(clientId))
                    {
                        // 検証完了

                        if (token_type_hint == OAuth2AndOIDCConst.AccessToken)
                        {
                            // 検証
                            AccessTokenFormatJwt verifier = new AccessTokenFormatJwt();
                            AuthenticationTicket ticket   = verifier.Unprotect(token);

                            if (ticket == null)
                            {
                                // 検証失敗
                                // 検証エラー
                                err.Add("error", "invalid_request");
                                err.Add("error_description", "invalid token");
                            }
                            else
                            {
                                // 検証成功

                                // jtiの取り出し
                                Claim jti = ticket.Identity.Claims.Where(
                                    x => x.Type == OAuth2AndOIDCConst.Claim_JwtId).FirstOrDefault <Claim>();

                                // access_token取消
                                OAuth2RevocationProvider.GetInstance().Create(jti.Value);
                                return(null); // 成功
                            }
                        }
                        else if (token_type_hint == OAuth2AndOIDCConst.RefreshToken)
                        {
                            // refresh_token取消
                            if (RefreshTokenProvider.DeleteDirectly(token))
                            {
                                // 取り消し成功
                                return(null); // 成功
                            }
                            else
                            {
                                // 取り消し失敗
                                err.Add("error", "invalid_request");
                                err.Add("error_description", "invalid token");
                            }
                        }
                        else
                        {
                            // token_type_hint パラメタ・エラー
                            err.Add("error", "invalid_request");
                            err.Add("error_description", "invalid token_type_hint");
                        }
                    }
                    else
                    {
                        // クライアント認証エラー(Credential不正
                        err.Add("error", "invalid_client");
                        err.Add("error_description", "Invalid credential");
                    }
                }
                else
                {
                    // クライアント認証エラー(Credential不正
                    err.Add("error", "invalid_client");
                    err.Add("error_description", "Invalid credential");
                }
            }
            else
            {
                // クライアント認証エラー(ヘッダ不正
                err.Add("error", "invalid_request");
                err.Add("error_description", "Invalid authentication header");
            }

            return(err); // 失敗
        }
예제 #17
0
        /// <summary>
        /// ChangeToIdTokenFromAccessToken
        ///   OIDC対応(AccessTokenからIdTokenを生成)
        /// </summary>
        /// <param name="access_token">string</param>
        /// <param name="code">string</param>
        /// <param name="HashClaimType">HashClaimType</param>
        /// <returns>IdToken</returns>
        /// <remarks>
        /// OIDC対応
        /// </remarks>

        public static string ChangeToIdTokenFromAccessToken(string access_token, string code, HashClaimType hct)
        {
            if (access_token.Contains("."))
            {
                string[] temp = access_token.Split('.');
                string   json = CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(temp[1]), CustomEncode.UTF_8);
                Dictionary <string, object> authTokenClaimSet = JsonConvert.DeserializeObject <Dictionary <string, object> >(json);

                // ・access_tokenがJWTで、payloadに"nonce" and "scope=openidクレームが存在する場合、
                if (authTokenClaimSet.ContainsKey("nonce") &&
                    authTokenClaimSet.ContainsKey("scopes"))
                {
                    JArray scopes = (JArray)authTokenClaimSet["scopes"];

                    // ・OpenID Connect : response_type=codeに対応する。
                    if (scopes.Any(x => x.ToString() == ASPNETIdentityConst.Scope_Openid))
                    {
                        //・payloadからscopeを削除する。
                        authTokenClaimSet.Remove("scopes");

                        //・payloadにat_hash, c_hashを追加する。
                        switch (hct)
                        {
                        case HashClaimType.None:
                            break;

                        case HashClaimType.AtHash:
                            // at_hash
                            authTokenClaimSet.Add(
                                "at_hash",
                                OidcTokenEditor.CreateHash(access_token));
                            break;

                        case HashClaimType.CHash:
                            // c_hash
                            authTokenClaimSet.Add(
                                "c_hash",
                                OidcTokenEditor.CreateHash(code));
                            break;

                        case HashClaimType.Both:
                            // at_hash, c_hash
                            authTokenClaimSet.Add(
                                "at_hash",
                                OidcTokenEditor.CreateHash(access_token));
                            authTokenClaimSet.Add(
                                "c_hash",
                                OidcTokenEditor.CreateHash(code));
                            break;
                        }

                        //・編集したpayloadを再度JWTとして署名する。
                        string    newPayload = JsonConvert.SerializeObject(authTokenClaimSet);
                        JWT_RS256 jwtRS256   = null;

                        // 署名
                        jwtRS256 = new JWT_RS256(ASPNETIdentityConfig.OAuthJWT_pfx, ASPNETIdentityConfig.OAuthJWTPassword,
                                                 X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);

                        string id_token = jwtRS256.Create(newPayload);

                        // 検証
                        jwtRS256 = new JWT_RS256(ASPNETIdentityConfig.OAuthJWT_cer, ASPNETIdentityConfig.OAuthJWTPassword,
                                                 X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);

                        if (jwtRS256.Verify(id_token))
                        {
                            // 検証できた。
                            return(id_token);
                        }
                        else
                        {
                            // 検証できなかった。
                        }
                    }
                    else
                    {
                        // OIDCでない。
                    }
                }
                else
                {
                    // OIDCでない。
                }
            }
            else
            {
                // JWTでない。
            }

            return("");
        }
예제 #18
0
        /// <summary>
        /// Authorization Code、Resource Owner Password Credentialsl、Client Credentialsグラント種別において、
        /// OAuthBearerTokenEndpointPathを処理する場合に発生する、" クライアント認証 " を行なうメソッド。
        /// " クライアント認証 "では、以下の両方の要素を検証する。
        /// ・context.ClientId が、登録された "client_id" であること。
        /// ・その他、資格情報が要求に存在していることを検証する。
        /// </summary>
        /// <param name="context">OAuthValidateClientAuthenticationContext</param>
        /// <returns>Task</returns>
        /// <see cref="https://msdn.microsoft.com/ja-jp/library/dn385497.aspx"/>
        public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            // クライアント識別子
            string clientId     = "";
            string clientSecret = "";

            // ・context.Validated を呼び出し、contextを検証完了に設定する。
            // ・検証完了にしなければ要求はそれ以上先には進まない。
            //context.Validated(clientId);

            #region クライアント認証を行なう。

            if (string.IsNullOrEmpty(context.Parameters[OAuth2AndOIDCConst.grant_type]))
            {
                // 指定なし。
                // 検証未完
            }
            else if (context.Parameters[OAuth2AndOIDCConst.grant_type].ToLower() == OAuth2AndOIDCConst.AuthorizationCodeGrantType)
            {
                #region Authorization Codeグラント種別

                // "client_id" および "client_secret"を基本認証の認証ヘッダから取得
                if (context.TryGetBasicCredentials(out clientId, out clientSecret))
                {
                    // 通常のクライアント認証
                    if (!(string.IsNullOrEmpty(clientId) && string.IsNullOrEmpty(clientSecret)))
                    {
                        // *.config or OAuth2Dataテーブルを参照してクライアント認証を行なう。
                        if (clientSecret == OAuth2Helper.GetInstance().GetClientSecret(context.ClientId))
                        {
                            // 検証完了
                            context.Validated(clientId);
                        }
                    }
                }
                else
                {
                    // その他のクライアント認証の可能性
                    string assertion = context.Parameters.Get(OAuth2AndOIDCConst.assertion);
                    if (!string.IsNullOrEmpty(assertion))
                    {
                        // JWT client assertion
                        Dictionary <string, string> dic = JsonConvert.DeserializeObject <Dictionary <string, string> >(
                            CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(
                                                          assertion.Split('.')[1]), CustomEncode.us_ascii));

                        string pubKey = OAuth2Helper.GetInstance().GetJwtAssertionPublickey(dic[OAuth2AndOIDCConst.iss]);
                        pubKey = CustomEncode.ByteToString(CustomEncode.FromBase64String(pubKey), CustomEncode.us_ascii);

                        if (!string.IsNullOrEmpty(pubKey))
                        {
                            string  iss    = "";
                            string  aud    = "";
                            string  scopes = "";
                            JObject jobj   = null;

                            if (JwtAssertion.VerifyJwtBearerTokenFlowAssertion(
                                    assertion, out iss, out aud, out scopes, out jobj, pubKey))
                            {
                                // aud 検証
                                if (aud == ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI
                                    + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint)
                                {
                                    // 検証完了
                                    context.Validated(iss);
                                }
                            }
                        }
                    }
                    else
                    {
                        // クライアント認証なしエラー
                    }
                }

                #endregion
            }
            else if (context.Parameters[OAuth2AndOIDCConst.grant_type].ToLower() == OAuth2AndOIDCConst.ResourceOwnerPasswordCredentialsGrantType)
            {
                #region Resource Owner Password Credentialsグラント種別

                #region 参考
                // Simple OAuth Server: Implementing a Simple OAuth Server with Katana
                // OAuth Authorization Server Components (Part 1) - Tugberk Ugurlu's Blog
                // http://www.tugberkugurlu.com/archive/simple-oauth-server-implementing-a-simple-oauth-server-with-katana-oauth-authorization-server-components-part-1
                // ・・・ 基本認証を使用する既存のクライアントを認証してOAuthに移行する。
                #endregion

                // "client_id" および "client_secret"を基本認証の認証ヘッダから取得
                if (context.TryGetBasicCredentials(out clientId, out clientSecret))
                {
                    if (!(string.IsNullOrEmpty(clientId) && string.IsNullOrEmpty(clientSecret)))
                    {
                        // *.config or OAuth2Dataテーブルを参照してクライアント認証を行なう。
                        if (clientSecret == OAuth2Helper.GetInstance().GetClientSecret(context.ClientId))
                        {
                            // 検証完了
                            context.Validated(clientId);
                        }
                    }
                }

                #endregion
            }
            else if (context.Parameters[OAuth2AndOIDCConst.grant_type].ToLower() == OAuth2AndOIDCConst.ClientCredentialsGrantType)
            {
                #region Client Credentialsグラント種別

                // "client_id" および "client_secret"を基本認証の認証ヘッダから取得
                if (context.TryGetBasicCredentials(out clientId, out clientSecret))
                {
                    if (!(string.IsNullOrEmpty(clientId) && string.IsNullOrEmpty(clientSecret)))
                    {
                        // *.config or OAuth2Dataテーブルを参照してクライアント認証を行なう。
                        if (clientSecret == OAuth2Helper.GetInstance().GetClientSecret(context.ClientId))
                        {
                            // 検証完了
                            context.Validated(clientId);
                        }
                    }
                }

                #endregion
            }
            else if (context.Parameters[OAuth2AndOIDCConst.grant_type].ToLower() == OAuth2AndOIDCConst.RefreshTokenGrantType)
            {
                #region RefreshToken

                if (!ASPNETIdentityConfig.EnableRefreshToken)
                {
                    throw new NotSupportedException(Resources.ApplicationOAuthBearerTokenProvider.EnableRefreshToken);
                }

                // "client_id" および "client_secret"を基本認証の認証ヘッダから取得
                if (context.TryGetBasicCredentials(out clientId, out clientSecret))
                {
                    if (!(string.IsNullOrEmpty(clientId) && string.IsNullOrEmpty(clientSecret)))
                    {
                        // *.config or OAuth2Dataテーブルを参照してクライアント認証を行なう。
                        if (clientSecret == OAuth2Helper.GetInstance().GetClientSecret(context.ClientId))
                        {
                            // 検証完了
                            context.Validated(clientId);
                        }
                    }
                }

                #endregion
            }
            else
            {
                // 不明な値
                // 検証未完
            }

            #endregion

            // 結果を返す。
            return(Task.FromResult(0));
        }
예제 #19
0
        /// <summary>Verify</summary>
        /// <param name="ro">string</param>
        /// <param name="iss">string</param>
        /// <param name="rsaPublicKey">RS256用のRSAParameters公開鍵</param>
        /// <returns>検証結果</returns>
        public static bool Verify(string ro, out string iss, RSAParameters rsaPublicKey)
        {
            iss = "";
            string aud           = "";
            string response_type = "";
            //string response_mode = "";
            //string redirect_uri = "";
            string scopes = "";
            string state  = "";
            string nonce  = "";
            //string prompt = "";
            //string login_hint = "";
            //JObject claims = null;

            JWS_RS256_Param jwtRS256 = new JWS_RS256_Param(rsaPublicKey);

            if (jwtRS256.Verify(ro))
            {
                string jwtPayload = CustomEncode.ByteToString(
                    CustomEncode.FromBase64UrlString(ro.Split('.')[1]), CustomEncode.UTF_8);

                JObject jobj = ((JObject)JsonConvert.DeserializeObject(jwtPayload));

                iss           = (string)jobj[OAuth2AndOIDCConst.iss];
                aud           = (string)jobj[OAuth2AndOIDCConst.aud];
                response_type = (string)jobj[OAuth2AndOIDCConst.response_type];

                //if(jobj.ContainsKey(OAuth2AndOIDCConst.response_mode))
                //    response_mode = (string)jobj[OAuth2AndOIDCConst.response_mode];
                //if (jobj.ContainsKey(OAuth2AndOIDCConst.redirect_uri))
                //    redirect_uri = (string)jobj[OAuth2AndOIDCConst.redirect_uri];

                scopes = (string)jobj[OAuth2AndOIDCConst.scope];
                state  = (string)jobj[OAuth2AndOIDCConst.state];
                nonce  = (string)jobj[OAuth2AndOIDCConst.nonce];

                //if (jobj.ContainsKey(OAuth2AndOIDCConst.prompt))
                //    prompt = (string)jobj[OAuth2AndOIDCConst.prompt];
                //if (jobj.ContainsKey(OAuth2AndOIDCConst.login_hint))
                //    login_hint = (string)jobj[OAuth2AndOIDCConst.login_hint];

                //if (jobj.ContainsKey(OAuth2AndOIDCConst.claims))
                //    claims = (JObject)jobj[OAuth2AndOIDCConst.claims];

                if (!string.IsNullOrEmpty(iss) &&
                    !string.IsNullOrEmpty(aud) &&
                    !string.IsNullOrEmpty(response_type) &&
                    !string.IsNullOrEmpty(scopes) &&
                    !string.IsNullOrEmpty(state) &&
                    !string.IsNullOrEmpty(nonce))
                {
                    // OK
                    return(true);
                }
                else
                {
                    // 必須項目の不足
                    return(true);
                }
            }
            else
            {
                // JWTの署名検証に失敗
                return(false);
            }
        }
예제 #20
0
        /// <summary>JWT生成</summary>
        private void btnJWTSign_Click(object sender, EventArgs e)
        {
            if (rbnJWTHS256.Checked)
            {
                // HS256
                string    password = GetPassword.Generate(20, 10);
                JWT_HS256 jwtHS256 = new JWT_HS256(CustomEncode.StringToByte(password, CustomEncode.UTF_8));

                // 生成
                string jwt = jwtHS256.Create(this.txtJWTPayload.Text);

                // 出力
                this.txtJWTKey.Text  = password;
                this.txtJWTJWK.Text  = jwtHS256.JWK;
                this.txtJWTSign.Text = jwt;

                // 改竄可能なフィールドに出力
                string[] temp = jwt.Split('.');
                this.txtJWTHeader.Text = CustomEncode.ByteToString(
                    CustomEncode.FromBase64UrlString(temp[0]), CustomEncode.UTF_8);
                this.txtJWTPayload.Text = CustomEncode.ByteToString(
                    CustomEncode.FromBase64UrlString(temp[1]), CustomEncode.UTF_8);
            }
            else if (rbnJWTRS256_XML.Checked)
            {
                // RS256 (XML)
                JWT_RS256_XML jwtRS256 = new JWT_RS256_XML();

                // 生成
                string jwt = jwtRS256.Create(this.txtJWTPayload.Text);

                // 出力
                this.txtJWTKey.Text = jwtRS256.XMLPublicKey;

                this.txtJWTJWK.Text =
                    RS256_KeyConverter.ParamToJwkPublicKey(
                        RS256_KeyConverter.XmlToProvider(jwtRS256.XMLPublicKey).ExportParameters(false));

                this.txtJWTSign.Text = jwt;

                // 改竄可能なフィールドに出力
                string[] temp = jwt.Split('.');
                this.txtJWTHeader.Text = CustomEncode.ByteToString(
                    CustomEncode.FromBase64UrlString(temp[0]), CustomEncode.UTF_8);
                this.txtJWTPayload.Text = CustomEncode.ByteToString(
                    CustomEncode.FromBase64UrlString(temp[1]), CustomEncode.UTF_8);
            }
            else if (rbnJWTRS256_Param.Checked)
            {
                // RS256 (Param)
                JWT_RS256_Param jwtRS256 = new JWT_RS256_Param();

                // 生成
                string jwt = jwtRS256.Create(this.txtJWTPayload.Text);

                // 出力
                this.txtJWTKey.Text = RS256_KeyConverter.ParamToXmlPublicKey(jwtRS256.RsaPublicParameters);
                this.txtJWTJWK.Text = RS256_KeyConverter.ParamToJwkPublicKey(jwtRS256.RsaPublicParameters);

                this.txtJWTSign.Text = jwt;

                // 改竄可能なフィールドに出力
                string[] temp = jwt.Split('.');
                this.txtJWTHeader.Text = CustomEncode.ByteToString(
                    CustomEncode.FromBase64UrlString(temp[0]), CustomEncode.UTF_8);
                this.txtJWTPayload.Text = CustomEncode.ByteToString(
                    CustomEncode.FromBase64UrlString(temp[1]), CustomEncode.UTF_8);
            }
            else
            {
                // RS256 (X509)
                JWT_RS256_X509 jwtRS256 = new JWT_RS256_X509(this.CertificateFilePath_pfx, this.CertificateFilePassword,
                                                             X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);

                // 生成
                string jwt = jwtRS256.Create(this.txtJWTPayload.Text);

                // 出力
                this.txtJWTKey.Text = jwtRS256.DigitalSignX509.X509PublicKey;

                this.txtJWTJWK.Text =
                    RS256_KeyConverter.ParamToJwkPublicKey(
                        RS256_KeyConverter.X509CerToProvider(
                            this.CertificateFilePath_cer).ExportParameters(false));

                this.txtJWTSign.Text = jwt;

                // 改竄可能なフィールドに出力
                string[] temp = jwt.Split('.');
                this.txtJWTHeader.Text = CustomEncode.ByteToString(
                    CustomEncode.FromBase64UrlString(temp[0]), CustomEncode.UTF_8);
                this.txtJWTPayload.Text = CustomEncode.ByteToString(
                    CustomEncode.FromBase64UrlString(temp[1]), CustomEncode.UTF_8);
            }
        }
예제 #21
0
        /// <summary>Unprotect</summary>
        /// <param name="jwt">JWT文字列</param>
        /// <returns>AuthenticationTicket</returns>
        public AuthenticationTicket Unprotect(string jwt)
        {
            // 空のケースあり。
            if (string.IsNullOrEmpty(jwt))
            {
                return(null);
            }

            // 検証
            JWT_RS256 jwtRS256 = new JWT_RS256(ASPNETIdentityConfig.OAuthJWT_cer, ASPNETIdentityConfig.OAuthJWTPassword);

            if (jwtRS256.Verify(jwt))
            {
                // 検証できた。

                // デシリアライズ、
                string[] temp = jwt.Split('.');
                string   json = CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(temp[1]), CustomEncode.UTF_8);
                Dictionary <string, object> authTokenClaimSet = JsonConvert.DeserializeObject <Dictionary <string, object> >(json);

                // 以下の検証処理
                //  ★ "iss": accounts.google.com的な,
                //  ★ "aud": client_id(クライアント識別子)
                //  ★ "sub": ユーザーの一意識別子(uname, email)
                //  ★ "exp": JWT の有効期限(Unix時間)
                //  ☆ "jti": JWT のID(OAuth Token Revocation)

                DateTime?datetime = OAuth2RevocationProvider.GetInstance().Get((string)authTokenClaimSet["jti"]);

                if (datetime == null)
                {
                    // authToken.iss, authToken.expの検証
                    if ((string)authTokenClaimSet["iss"] == ASPNETIdentityConfig.OAuthIssuerId &&
                        OAuth2Helper.GetInstance().GetClientSecret((string)authTokenClaimSet["aud"]) != null &&
                        long.Parse((string)authTokenClaimSet["exp"]) >= DateTimeOffset.Now.ToUnixTimeSeconds())
                    {
                        // authToken.subの検証
                        // ApplicationUser を取得する。
                        ApplicationUserManager userManager
                            = HttpContext.Current.GetOwinContext().GetUserManager <ApplicationUserManager>();
                        ApplicationUser user = userManager.FindByName((string)authTokenClaimSet["sub"]); // 同期版でOK。

                        if (user != null)
                        {
                            // User Accountの場合

                            // ユーザーに対応するClaimsIdentityを生成し、
                            ClaimsIdentity identity = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ExternalBearer);

                            // aud、scopes、nonceなどのClaimを追加する。
                            List <string> scopes = new List <string>();
                            foreach (string s in (JArray)authTokenClaimSet["scopes"])
                            {
                                scopes.Add(s);
                            }

                            OAuth2Helper.AddClaim(identity,
                                                  (string)authTokenClaimSet["aud"], "", scopes,  (string) authTokenClaimSet["nonce"]);

                            // その他、所定のClaimを追加する。
                            identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_ExpirationTime, (string)authTokenClaimSet["exp"]));
                            identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_NotBefore, (string)authTokenClaimSet["nbf"]));
                            identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_IssuedAt, (string)authTokenClaimSet["iat"]));
                            identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_JwtId, (string)authTokenClaimSet["jti"]));

                            // AuthenticationPropertiesの生成
                            AuthenticationProperties prop = new AuthenticationProperties();
                            prop.IssuedUtc  = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["iat"]));
                            prop.ExpiresUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["exp"]));

                            AuthenticationTicket auth = new AuthenticationTicket(identity, prop);

                            // 認証結果を返す。
                            return(auth);
                        }
                        else
                        {
                            // Client Accountの場合

                            // ClaimとStoreのAudience(aud)に対応するSubject(sub)が一致するかを確認し、一致する場合のみ、認証する。
                            // ※ でないと、UserStoreから削除されたUser Accountが、Client Accountに化けることになる。
                            if ((string)authTokenClaimSet["sub"] == OAuth2Helper.GetInstance().GetClientName((string)authTokenClaimSet["aud"]))
                            {
                                // ClaimsIdentityを生成し、
                                ClaimsIdentity identity = new ClaimsIdentity(DefaultAuthenticationTypes.ExternalBearer);

                                // sub(client_idに対応するclient_name)Claimを設定する。
                                identity.AddClaim(new Claim(ClaimTypes.Name, (string)authTokenClaimSet["sub"]));

                                // aud、scopes、nonceなどのClaimを追加する。
                                List <string> scopes = new List <string>();
                                foreach (string s in (JArray)authTokenClaimSet["scopes"])
                                {
                                    scopes.Add(s);
                                }

                                OAuth2Helper.AddClaim(identity,
                                                      (string)authTokenClaimSet["aud"], "", scopes, (string)authTokenClaimSet["nonce"]);

                                // その他、所定のClaimを追加する。
                                identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_ExpirationTime, (string)authTokenClaimSet["exp"]));
                                identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_NotBefore, (string)authTokenClaimSet["nbf"]));
                                identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_IssuedAt, (string)authTokenClaimSet["iat"]));
                                identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_JwtId, (string)authTokenClaimSet["jti"]));

                                // AuthenticationPropertiesの生成
                                AuthenticationProperties prop = new AuthenticationProperties();
                                prop.IssuedUtc  = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["iat"]));
                                prop.ExpiresUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["exp"]));

                                AuthenticationTicket auth = new AuthenticationTicket(identity, prop);

                                // 認証結果を返す。
                                return(auth);
                            }
                        }
                    }
                    else
                    {
                        // クレーム検証の失敗
                    }
                }
                else
                {
                    // 取り消し済み
                }
            }
            else
            {
                // JWT署名検証の失敗
            }

            // 検証、認証ナドナド、できなかった。
            return(null);
        }
예제 #22
0
        /// <summary>Unprotect</summary>
        /// <param name="jwt">JWT文字列</param>
        /// <returns>AuthenticationTicket</returns>
        public AuthenticationTicket Unprotect(string jwt)
        {
            // 検証
            JWT_RS256 jwtRS256 = new JWT_RS256(ASPNETIdentityConfig.OAuthJWT_cer, ASPNETIdentityConfig.OAuthJWTPassword);

            if (jwtRS256.Verify(jwt))
            {
                // 検証できた。

                // デシリアライズ、
                string[] temp = jwt.Split('.');
                string   json = CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(temp[1]), CustomEncode.UTF_8);
                Dictionary <string, object> authTokenClaimSet = JsonConvert.DeserializeObject <Dictionary <string, object> >(json);

                // 以下の検証処理
                //  ★ "iss":"accounts.google.com",
                //  ★ "aud":"クライアント識別子.apps.googleusercontent.com",
                //  ★ "sub":"ユーザーの一意識別子",
                //  ★ "exp":JWT の有効期限(Unix時間)
                //  ☆ "nonce":Implicitで必須

                // authToken.iss, authToken.expの検証
                if ((string)authTokenClaimSet["iss"] == ASPNETIdentityConfig.OAuthIssuerId &&
                    OAuth2ProviderHelper.GetInstance().GetClientSecret((string)authTokenClaimSet["aud"]) != null &&
                    long.Parse((string)authTokenClaimSet["exp"]) >= DateTimeOffset.Now.ToUnixTimeSeconds())
                {
                    // authToken.subの検証
                    // ApplicationUser を取得する。
                    ApplicationUserManager userManager
                        = HttpContext.Current.GetOwinContext().GetUserManager <ApplicationUserManager>();
                    ApplicationUser user = userManager.FindByName((string)authTokenClaimSet["sub"]); // 同期版でOK。

                    if (user != null)
                    {
                        // User Accountの場合

                        // ユーザーに対応するClaimsIdentityを生成する。
                        ClaimsIdentity identity = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ExternalBearer);

                        // ClaimsIdentityに、その他、所定のClaimを追加する。
                        List <string> scopes = new List <string>();
                        foreach (string s in (JArray)authTokenClaimSet["scopes"])
                        {
                            scopes.Add(s);
                        }
                        OAuth2ProviderHelper.AddClaim(identity,
                                                      (string)authTokenClaimSet["aud"],
                                                      "", (string)authTokenClaimSet["nonce"], scopes);

                        // AuthenticationPropertiesの生成
                        AuthenticationProperties prop = new AuthenticationProperties();

                        // AuthenticationTicketに格納不要
                        //prop.IssuedUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["iat"]));
                        //prop.ExpiresUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["exp"]));

                        AuthenticationTicket auth = new AuthenticationTicket(identity, prop);

                        // 認証結果を返す。
                        return(auth);
                    }
                    else
                    {
                        // Client Accountの場合

                        // ClaimとStoreのAudienceに対応するSubjectが一致するかを確認し、一致する場合のみ、認証する。
                        // でないと、UserStoreから削除されたUser Accountが、Client Accountに化けることになる。
                        if ((string)authTokenClaimSet["sub"] == OAuth2ProviderHelper.GetInstance().GetClientName((string)authTokenClaimSet["aud"]))
                        {
                            // ClaimsIdentityを生成し、
                            ClaimsIdentity identity = new ClaimsIdentity(OAuthDefaults.AuthenticationType);

                            // ClaimsIdentityに、client_idに対応するclient_nameを設定する。
                            identity.AddClaim(new Claim(ClaimTypes.Name, (string)authTokenClaimSet["sub"]));

                            // ClaimsIdentityに、その他、所定のClaimを追加する。
                            List <string> scopes = new List <string>();
                            foreach (string s in (JArray)authTokenClaimSet["scopes"])
                            {
                                scopes.Add(s);
                            }

                            OAuth2ProviderHelper.AddClaim(identity,
                                                          (string)authTokenClaimSet["aud"],
                                                          "", (string)authTokenClaimSet["nonce"], scopes);

                            // AuthenticationPropertiesの生成
                            AuthenticationProperties prop = new AuthenticationProperties();

                            // AuthenticationTicketに格納不要
                            //prop.IssuedUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["iat"]));
                            //prop.ExpiresUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["exp"]));

                            AuthenticationTicket auth = new AuthenticationTicket(identity, prop);

                            // 認証結果を返す。
                            return(auth);
                        }
                    }
                }
            }

            // 検証、認証ナドナド、できなかった。
            return(null);
        }
예제 #23
0
 /// <summary>暗号化</summary>
 /// <param name="msg">暗号化するメッセージ</param>
 /// <returns>暗号化したメッセージ</returns>
 public string Encrypt(string msg)
 {
     return(CustomEncode.ByteToString(
                this.Encrypt(CustomEncode.StringToByte(msg, CustomEncode.UTF_8)),
                CustomEncode.UTF_8));
 }
예제 #24
0
파일: Form1.cs 프로젝트: ukayare/OpenTouryo
 /// <summary>秘密鍵・復号化</summary>
 private void button2_Click(object sender, EventArgs e)
 {
     if (string.IsNullOrEmpty(txtSCSalt.Text))
     {
         // ソルト無し
         if (this.rbnSCString.Checked)
         {
             // String
             this.txtSCString.Text =
                 SymmetricCryptography.DecryptString(
                     this.txtSCCode.Text,
                     this.txtSCPassword.Text,
                     (EnumSymmetricAlgorithm)cbxSCPV.SelectedValue);
         }
         else
         {
             // Bytes
             this.txtSCString.Text =
                 CustomEncode.ByteToString(
                     SymmetricCryptography.DecryptBytes(
                         CustomEncode.FormHexString(this.txtSCCode.Text),
                         this.txtSCPassword.Text,
                         (EnumSymmetricAlgorithm)cbxSCPV.SelectedValue),
                     CustomEncode.UTF_8);
         }
     }
     else
     {
         // ソルト有り
         if (this.nudSCStretching.Value == 0)
         {
             // ストレッチング無し
             if (this.rbnSCString.Checked)
             {
                 // String
                 this.txtSCString.Text
                     = SymmetricCryptography.DecryptString(
                           this.txtSCCode.Text,
                           this.txtSCPassword.Text,
                           (EnumSymmetricAlgorithm)cbxSCPV.SelectedValue,
                           CustomEncode.StringToByte(txtSCSalt.Text, CustomEncode.UTF_8));
             }
             else
             {
                 // Bytes
                 this.txtSCString.Text =
                     CustomEncode.ByteToString(
                         SymmetricCryptography.DecryptBytes(
                             CustomEncode.FormHexString(this.txtSCCode.Text),
                             this.txtSCPassword.Text,
                             (EnumSymmetricAlgorithm)cbxSCPV.SelectedValue,
                             CustomEncode.StringToByte(txtSCSalt.Text, CustomEncode.UTF_8)),
                         CustomEncode.UTF_8);
             }
         }
         else
         {
             // ストレッチング有り
             if (this.rbnSCString.Checked)
             {
                 // String
                 this.txtSCString.Text
                     = SymmetricCryptography.DecryptString(
                           this.txtSCCode.Text,
                           this.txtSCPassword.Text,
                           (EnumSymmetricAlgorithm)cbxSCPV.SelectedValue,
                           CustomEncode.StringToByte(txtSCSalt.Text, CustomEncode.UTF_8),
                           (int)this.nudSCStretching.Value);
             }
             else
             {
                 // Bytes
                 this.txtSCString.Text =
                     CustomEncode.ByteToString(
                         SymmetricCryptography.DecryptBytes(
                             CustomEncode.FormHexString(this.txtSCCode.Text),
                             this.txtSCPassword.Text,
                             (EnumSymmetricAlgorithm)cbxSCPV.SelectedValue,
                             CustomEncode.StringToByte(txtSCSalt.Text, CustomEncode.UTF_8),
                             (int)this.nudSCStretching.Value),
                         CustomEncode.UTF_8);
             }
         }
     }
 }