示例#1
0
        /// <summary>ChangeToIdTokenFromJwt</summary>
        /// <param name="access_token">Jwt (string)</param>
        /// <returns>IdToken (string)</returns>
        public static string ChangeToIdTokenFromJwt(string access_token)
        {
            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を再度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("");
        }
示例#2
0
        /// <summary>JwkToParam</summary>
        /// <param name="jwkObject">JObject</param>
        /// <returns>RSAParameters(公開鍵)</returns>
        public RSAParameters JwkToParam(JObject jwkObject)
        {
            if (jwkObject[JwtConst.kty].ToString().ToUpper() == JwtConst.RSA)
            {
                // RSAParameters
                // FromBase64Stringだとエラーになる。
                RSAParameters rsaParameters = new RSAParameters()
                {
                    // Public
                    Modulus  = CustomEncode.FromBase64UrlString((string)jwkObject[JwtConst.n]),
                    Exponent = CustomEncode.FromBase64UrlString((string)jwkObject[JwtConst.e]),

                    // Private
                    D        = CustomEncode.FromBase64UrlString((string)jwkObject[JwtConst.d]),
                    P        = CustomEncode.FromBase64UrlString((string)jwkObject[JwtConst.p]),
                    Q        = CustomEncode.FromBase64UrlString((string)jwkObject[JwtConst.q]),
                    DP       = CustomEncode.FromBase64UrlString((string)jwkObject[JwtConst.dp]),
                    DQ       = CustomEncode.FromBase64UrlString((string)jwkObject[JwtConst.dq]),
                    InverseQ = CustomEncode.FromBase64UrlString((string)jwkObject[JwtConst.qi])
                };

                return(rsaParameters);
            }

            throw new ArgumentOutOfRangeException("jwkObject", jwkObject, "Invalid");
        }
示例#3
0
        /// <summary>Init</summary>
        /// <param name="jwkString">string</param>
        public void Init(string jwkString)
        {
            Dictionary <string, string> jwk = new Dictionary <string, string>();

            jwk = JsonConvert.DeserializeObject <Dictionary <string, string> >(jwkString);

            if (jwk.ContainsKey(JwtConst.kty) &&
                jwk.ContainsKey(JwtConst.use) &&
                jwk.ContainsKey(JwtConst.alg) &&
                jwk.ContainsKey(JwtConst.k))
            {
                // 正しいキー
                if (jwk[JwtConst.kty].ToLower() == "oct" &&
                    jwk[JwtConst.use].ToLower() == "sig" &&
                    jwk[JwtConst.alg].ToUpper() == this.JwtConstHSnnn &&
                    !string.IsNullOrEmpty(jwk[JwtConst.k]))
                {
                    // 正しい値
                    this.JWK = jwkString;
                    this.Key = CustomEncode.FromBase64UrlString(jwk[JwtConst.k]);
                    return; // 正常終了
                }
                else
                {
                }
            }
            else
            {
            }

            // 異常終了
            throw new ArgumentException(
                      PublicExceptionMessage.ARGUMENT_INCORRECT,
                      "The JWK of " + this.JwtConstHSnnn + " is incorrect.");
        }
示例#4
0
        /// <summary>Constructor</summary>
        /// <param name="jwkString">string</param>
        public JWT_HS256(string jwkString)
        {
            Dictionary <string, string> jwk = new Dictionary <string, string>();

            jwk = JsonConvert.DeserializeObject <Dictionary <string, string> >(jwkString);

            if (jwk.ContainsKey("kty") &&
                jwk.ContainsKey("use") &&
                jwk.ContainsKey("alg") &&
                jwk.ContainsKey("k"))
            {
                // 正しいキー
                if (jwk["kty"] == "oct" &&
                    jwk["use"] == "sig" &&
                    jwk["alg"] == "HS256" &&
                    !string.IsNullOrEmpty(jwk["k"]))
                {
                    // 正しい値
                    this.JWK = jwkString;
                    this.Key = CustomEncode.FromBase64UrlString(jwk["k"]);
                    return; // 正常終了
                }
                else
                {
                }
            }
            else
            {
            }

            // 異常終了
            throw new ArgumentException(
                      PublicExceptionMessage.ARGUMENT_INCORRECT,
                      "The JWK of HS256 is incorrect.");
        }
 /// <summary>JwkToCng</summary>
 /// <param name="jwk">JObject</param>
 /// <returns>CngKey(公開鍵)</returns>
 public static CngKey JwkToCng(Dictionary <string, string> jwk)
 {
     // 楕円曲線
     // 不要
     // 公開鍵の部分
     return(EccKey.New(
                CustomEncode.FromBase64UrlString((string)jwk[JwtConst.x]),
                CustomEncode.FromBase64UrlString((string)jwk[JwtConst.y])));
 }
示例#6
0
        /// <summary>InspectJwe</summary>
        /// <param name="testLabel">string</param>
        /// <param name="jwe">string[]</param>
        public static void InspectJwe(string testLabel, string[] jwe)
        {
            MyDebug.OutputDebugAndConsole(testLabel, "JWE Header: " +
                                          CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(jwe[0]), CustomEncode.UTF_8));

            MyDebug.OutputDebugAndConsole(testLabel, "JWE Encrypted Key: " + jwe[1]);
            MyDebug.OutputDebugAndConsole(testLabel, "JWE Initialization Vector: " + jwe[2]);
            MyDebug.OutputDebugAndConsole(testLabel, "JWE Ciphertext: " + jwe[3]);
            MyDebug.OutputDebugAndConsole(testLabel, "JWE Authentication Tag: " + jwe[4]);
        }
示例#7
0
        /// <summary>InspectJws</summary>
        /// <param name="testLabel">string</param>
        /// <param name="jws">string[]</param>
        public static void InspectJws(string testLabel, string[] jws)
        {
            MyDebug.OutputDebugAndConsole(testLabel, "JWS Header: " +
                                          CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(jws[0]), CustomEncode.UTF_8));

            MyDebug.OutputDebugAndConsole(testLabel, "JWS Payload: " +
                                          CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(jws[1]), CustomEncode.UTF_8));

            MyDebug.OutputDebugAndConsole(testLabel, "JWS Signature: " + jws[2]);
        }
示例#8
0
        /// <summary>VerifyCiba</summary>
        /// <param name="ro">string</param>
        /// <param name="iss">string</param>
        /// <param name="ecPublicKey">ES256用のECParameters公開鍵</param>
        /// <returns>検証結果</returns>
        public static bool VerifyCiba(string ro, out string iss, ECParameters ecPublicKey)
        {
            iss = "";
            string aud    = "";
            string exp    = "";
            string nbf    = "";
            string scopes = "";
            string client_notification_token = "";
            string binding_message           = "";
            string login_hint = "";

            JWS_ES256_Param jwtES256 = new JWS_ES256_Param(ecPublicKey, false);

            if (jwtES256.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];
                exp    = (string)jobj[OAuth2AndOIDCConst.exp];
                nbf    = (string)jobj[OAuth2AndOIDCConst.nbf];
                scopes = (string)jobj[OAuth2AndOIDCConst.scope];
                client_notification_token = (string)jobj[OAuth2AndOIDCConst.client_notification_token];
                binding_message           = (string)jobj[OAuth2AndOIDCConst.binding_message];
                login_hint = (string)jobj[OAuth2AndOIDCConst.login_hint];

                //if (...requestContextAndIntent

                if (!string.IsNullOrEmpty(iss) &&
                    !string.IsNullOrEmpty(aud) &&
                    !string.IsNullOrEmpty(exp) &&
                    !string.IsNullOrEmpty(nbf) &&
                    !string.IsNullOrEmpty(scopes) &&
                    !string.IsNullOrEmpty(client_notification_token) &&
                    !string.IsNullOrEmpty(binding_message) &&
                    !string.IsNullOrEmpty(login_hint))
                {
                    // OK
                    return(true);
                }
                else
                {
                    // 必須項目の不足
                    return(true);
                }
            }
            else
            {
                // JWTの署名検証に失敗
                return(false);
            }
        }
示例#9
0
        /// <summary>JWE復号メソッド</summary>
        /// <param name="jwtString">JWEの文字列表現</param>
        /// <param name="payloadJson">ペイロード部のJson文字列</param>
        /// <returns>復号の結果</returns>
        public bool Decrypt(string jwtString, out string payloadJson)
        {
            try
            {
                string[] temp = jwtString.Split('.');

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

                if (headerObject.alg.ToUpper() == JWEHeader.alg.ToUpper() &&
                    headerObject.enc.ToUpper() == JWEHeader.enc.ToUpper() &&
                    headerObject.typ.ToUpper() == JWEHeader.typ.ToUpper())
                {
                    // コンテンツ暗号化キー(CEK)
                    byte[] encryptedCekBytes = CustomEncode.FromBase64UrlString(temp[1]);
                    byte[] cekBytes          = this.DecryptKey(encryptedCekBytes); // 派生を呼ぶ

                    // 初期化ベクトル
                    byte[] ivBytes = CustomEncode.FromBase64UrlString(temp[2]);

                    // 追加認証データ(AAD)
                    byte[] aadBytes = CustomEncode.StringToByte(temp[0], CustomEncode.us_ascii);

                    // ペイロード(認証付き暗号(AEAD)による暗号化)
                    byte[] encryptedPayloadBytes = CustomEncode.FromBase64UrlString(temp[3]);

                    // 認証タグ(MAC)
                    byte[] macBytes = CustomEncode.FromBase64UrlString(temp[4]);

                    // 復号化
                    byte[] payloadBytes = this.DecryptBody( // 派生を呼ぶ
                        cekBytes, ivBytes, aadBytes, new AeadResult()
                    {
                        Ciphert = encryptedPayloadBytes,
                        Tag     = macBytes
                    });

                    payloadJson = CustomEncode.ByteToString(payloadBytes, CustomEncode.UTF_8);
                    return(true);
                }
                else
                {
                    payloadJson = "";
                    return(false);
                }
            }
            catch
            {
                payloadJson = "";
                return(false);
            }
        }
示例#10
0
        /// <summary>JwkToParam</summary>
        /// <param name="jwk">JObject</param>
        /// <returns>ECParameters(公開鍵)</returns>
        public ECParameters JwkToParam(Dictionary <string, string> jwk)
        {
            ECParameters ecParams = new ECParameters();

            // 楕円曲線
            ecParams.Curve = this.ECCurveDic[(string)jwk[JwtConst.crv]];

            // Public
            ecParams.Q.X = CustomEncode.FromBase64UrlString((string)jwk[JwtConst.x]);
            ecParams.Q.Y = CustomEncode.FromBase64UrlString((string)jwk[JwtConst.y]);
            // Private
            ecParams.D = CustomEncode.FromBase64UrlString((string)jwk[JwtConst.d]);

            return(ecParams);
        }
示例#11
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 scopes        = "";
            string state         = "";
            string nonce         = "";

            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];
                scopes        = (string)jobj[OAuth2AndOIDCConst.scope];
                state         = (string)jobj[OAuth2AndOIDCConst.state];
                nonce         = (string)jobj[OAuth2AndOIDCConst.nonce];

                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);
            }
        }
示例#12
0
        /// <summary>VerifyJwtBearerTokenFlowAssertion</summary>
        /// <param name="jwtAssertion">string</param>
        /// <param name="iss">client_id</param>
        /// <param name="aud">Token2 EndPointのuri</param>
        /// <param name="scopes">scopes</param>
        /// <param name="jobj">JObject</param>
        /// <param name="rsaPublicKey">RS256用のRSAParameters公開鍵</param>
        /// <returns>検証結果</returns>
        public static bool VerifyJwtBearerTokenFlowAssertion(string jwtAssertion,
                                                             out string iss, out string aud, out string scopes, out JObject jobj, RSAParameters rsaPublicKey)
        {
            iss    = "";
            aud    = "";
            scopes = "";
            jobj   = null;

            JWS_RS256_Param jwtRS256 = new JWS_RS256_Param(rsaPublicKey);

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

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

                iss = (string)jobj[OAuth2AndOIDCConst.iss];
                aud = (string)jobj[OAuth2AndOIDCConst.aud];
                //string iat = (string)jobj[OAuth2AndOIDCConst.iat];
                scopes = (string)jobj[OAuth2AndOIDCConst.scope];

                long unixTimeSeconds = 0;
#if NET45
                unixTimeSeconds = PubCmnFunction.ToUnixTime(DateTimeOffset.Now);
#else
                unixTimeSeconds = DateTimeOffset.Now.ToUnixTimeSeconds();
#endif
                string exp = (string)jobj[OAuth2AndOIDCConst.exp];
                if (long.Parse(exp) >= unixTimeSeconds)
                {
                    return(true);
                }
                else
                {
                    // JWTの内容検証に失敗
                }
            }
            else
            {
                // JWTの署名検証に失敗
            }

            // 認証に失敗
            return(false);
        }
        /// <summary>JwkToParam</summary>
        /// <param name="jwkObject">JObject</param>
        /// <returns>ECParameters(公開鍵)</returns>
        public static ECParameters JwkToParam(JObject jwkObject)
        {
            ECParameters ecParams = new ECParameters();

            // 楕円曲線
            ecParams.Curve = EccPublicKeyConverter.ECCurveDic[(string)jwkObject[JwtConst.crv]];

            // 公開鍵の部分
            ecParams.Q.X = CustomEncode.FromBase64UrlString((string)jwkObject[JwtConst.x]);
            ecParams.Q.Y = CustomEncode.FromBase64UrlString((string)jwkObject[JwtConst.y]);
            //if (jwk.ContainsKey(JwtConst.d)) // 秘密鍵の部分は処理しない
            //{
            //    ecParams.D = CustomEncode.FromBase64UrlString((string)jwk[JwtConst.d]);
            //}

            return(ecParams);
        }
示例#14
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);
            }
        }
示例#15
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);
            }
        }
示例#16
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);
            }
        }
示例#17
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));
        }
示例#18
0
        /// <summary>ValidateSignature</summary>

        /// <param name="clientData">string</param>
        /// <param name="authenticatorData">string</param>
        /// <param name="signature">string</param>
        /// <returns>
        /// true  : valid
        /// false : invalid
        /// </returns>
        public bool ValidateSignature(
            string clientData, string authenticatorData, string signature)
        {
            bool ret = false;

            byte[] clientDataBytes        = CustomEncode.FromBase64UrlString(clientData);
            byte[] authenticatorDataBytes = CustomEncode.FromBase64UrlString(authenticatorData);
            byte[] signatureBytes         = CustomEncode.FromBase64UrlString(signature);

            // Challengeの一致を確認する。
            JObject clientJson = JObject.Parse(//Encoding.ASCII.GetString(clientDataBytes));
                Encoding.ASCII.GetString(clientDataBytes).Replace("\0", "").Trim());

            byte[] hashBytes = null;
            byte[] data      = null;
            hashBytes = GetHash.GetHashBytes(clientDataBytes, EnumHashAlgorithm.SHA256Managed, 0);
            data      = authenticatorDataBytes.Concat(hashBytes).ToArray();

            if ((string)clientJson["challenge"] == this.Challenge)
            {
                // Challengeの一致

                // Load public key
                RSACryptoServiceProvider rsaCryptoServiceProvider =
                    RS256_KeyConverter.JwkToProvider(this.PublicKey);

                // VerifyData
                ret = rsaCryptoServiceProvider.VerifyData(
                    data, signatureBytes,
                    HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

                return(ret);
            }
            else
            {
                // Challengeの不一致
                return(false);
            }
        }
示例#19
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);
            }
        }
示例#20
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);
            }
        }
示例#21
0
        /// <summary>
        /// JwkToProvider
        /// Jwk公開鍵からRSAProviderへ変換
        /// </summary>
        /// <param name="jwkPublicKey">jwkPublicKey</param>
        /// <returns>
        /// RSACryptoServiceProvider
        ///   rsaCryptoServiceProvider.VerifyData(
        ///     data, signatureBytes,
        ///     HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
        /// </returns>
        public static RSACryptoServiceProvider JwkToProvider(string jwkPublicKey)
        {
            JObject jwk = JObject.Parse(jwkPublicKey);

            if (jwk["alg"].ToString().ToLower() == "rs256")
            {
                // RSAParameters
                // FromBase64Stringだとエラーになる。
                RSAParameters rsaParameters = new RSAParameters()
                {
                    Modulus  = CustomEncode.FromBase64UrlString((string)jwk["n"]),
                    Exponent = CustomEncode.FromBase64UrlString((string)jwk["e"]),
                };

                RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
                rsaCryptoServiceProvider.ImportParameters(rsaParameters);

                return(rsaCryptoServiceProvider);
            }
            else
            {
                return(null);
            }
        }
示例#22
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);
        }
示例#23
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); // 失敗
        }
示例#24
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));
        }
示例#25
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);
            }
        }
示例#26
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);
        }
示例#27
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);
        }