Exemple #1
0
        /// <summary>CreateByRsa</summary>
        /// <param name="iss">client_id</param>
        /// <param name="aud">Token2 EndPointのuri</param>
        /// <param name="forExp">DateTimeOffset</param>
        /// <param name="scopes">scopes</param>
        /// <param name="rsaPrivateKey">RS256用のRSAParameters秘密鍵</param>
        /// <returns>JwtAssertion</returns>
        public static string CreateByRsa(
            string iss, string aud, TimeSpan forExp, string scopes, RSAParameters rsaPrivateKey)
        {
            string json = "";

            //string jws = "";

            #region ClaimSetの生成

            Dictionary <string, object> jwtAssertionClaimSet = new Dictionary <string, object>();

            jwtAssertionClaimSet.Add(OAuth2AndOIDCConst.iss, iss); // client_id
            jwtAssertionClaimSet.Add(OAuth2AndOIDCConst.aud, aud); // Token EndPointのuri。

            jwtAssertionClaimSet.Add(OAuth2AndOIDCConst.exp, CmnJwtToken.CreateExpClaim(forExp));
            jwtAssertionClaimSet.Add(OAuth2AndOIDCConst.iat, CmnJwtToken.CreateIatClaim());

            jwtAssertionClaimSet.Add(OAuth2AndOIDCConst.jti, CmnJwtToken.CreateJitClaim());
            jwtAssertionClaimSet.Add(OAuth2AndOIDCConst.scope, scopes); // scopes

            json = JsonConvert.SerializeObject(jwtAssertionClaimSet);

            #endregion

            #region JWT化

            JWS_RS256_Param jwtRS256 = new JWS_RS256_Param(rsaPrivateKey);
            return(jwtRS256.Create(json));

            #endregion
        }
Exemple #2
0
        /// <summary>CreateByECDsa</summary>
        /// <param name="iss">client_id</param>
        /// <param name="aud">Token2 EndPointのuri</param>
        /// <param name="forExp">DateTimeOffset</param>
        /// <param name="scopes">scopes</param>
        /// <param name="ecdsaX509FilePath">ES256用の X.509秘密鍵 の File Path</param>
        /// <param name="ecdsaX509Password">ES256用の X.509秘密鍵 の Password</param>
        /// <returns>JwtAssertion</returns>
        public static string CreateByECDsa(
            string iss, string aud, TimeSpan forExp, string scopes,
            string ecdsaX509FilePath, string ecdsaX509Password)
        ///// <param name="eccPrivateKey">ES256用のECParameters秘密鍵</param>
        //ECParameters ecPrivateKey) // ECDsa.ExportParameters(true)が動かねぇ。
        {
            string json = "";

            //string jws = "";

            #region ClaimSetの生成

            Dictionary <string, object> jwtAssertionClaimSet = new Dictionary <string, object>();

            jwtAssertionClaimSet.Add(OAuth2AndOIDCConst.iss, iss); // client_id
            jwtAssertionClaimSet.Add(OAuth2AndOIDCConst.aud, aud); // Token EndPointのuri。

            jwtAssertionClaimSet.Add(OAuth2AndOIDCConst.exp, CmnJwtToken.CreateExpClaim(forExp));
            jwtAssertionClaimSet.Add(OAuth2AndOIDCConst.iat, CmnJwtToken.CreateIatClaim());

            jwtAssertionClaimSet.Add(OAuth2AndOIDCConst.jti, CmnJwtToken.CreateJitClaim());
            jwtAssertionClaimSet.Add(OAuth2AndOIDCConst.scope, scopes); // scopes

            json = JsonConvert.SerializeObject(jwtAssertionClaimSet);

            #endregion

            #region JWT化

            JWS_ES256_X509 jwtES256 = new JWS_ES256_X509(ecdsaX509FilePath, ecdsaX509Password);
            return(jwtES256.Create(json));

            #endregion
        }
        // - OpenID Connect Client Initiated Backchannel Authentication Flow - Core 1.0 draft-01
        //   https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html
        // - Financial-grade API: Client Initiated Backchannel Authentication Profile
        //   https://openid.net/specs/openid-financial-api-ciba-ID1.html

        #region Create
        ///// <summary>CreateCiba</summary>
        ///// <param name="iss">string</param>
        ///// <param name="aud">string</param>
        ///// <param name="exp">string</param>
        ///// <param name="nbf">string</param>
        ///// <param name="scopes">string</param>
        ///// <param name="client_notification_token">string</param>
        ///// <param name="binding_message">string</param>
        ///// <param name="user_code">string</param>
        ///// <param name="requested_expiry">string</param>
        ///// <param name="login_hint">string</param>
        ///// <param name="requestContextAndIntent">Dictionary(string, object)</param>
        ///// <param name="jwkPrivateKey">ES256用のJWK秘密鍵</param>
        ///// <returns>RequestObject</returns>
        //public static string CreateCiba(
        //    string iss, string aud, string exp, string nbf, string scopes,
        //    string client_notification_token, string binding_message,
        //    string user_code, string requested_expiry, string login_hint,
        //    Dictionary<string, object> requestContextAndIntent, string jwkPrivateKey)
        //{
        //    EccPrivateKeyConverter epkc = new EccPrivateKeyConverter();
        //    return RequestObject.CreateCiba(
        //        iss, aud, exp, nbf, scopes,
        //        client_notification_token, binding_message,
        //        user_code, requested_expiry, login_hint,
        //        requestContextAndIntent, epkc.JwkToParam(jwkPrivateKey));
        //}

        /// <summary>CreateCiba</summary>
        /// <param name="iss">string</param>
        /// <param name="aud">string</param>
        /// <param name="exp">string</param>
        /// <param name="nbf">string</param>
        /// <param name="scopes">string</param>
        /// <param name="client_notification_token">string</param>
        /// <param name="binding_message">string</param>
        /// <param name="user_code">string</param>
        /// <param name="requested_expiry">string</param>
        /// <param name="login_hint">string</param>
        /// <param name="requestContextAndIntent">Dictionary(string, object)</param>
        /// <param name="ecdsaX509FilePath">ES256用の X.509秘密鍵 の File Path</param>
        /// <param name="ecdsaX509Password">ES256用の X.509秘密鍵 の Password</param>
        /// <returns>RequestObject</returns>
        public static string CreateCiba(
            string iss, string aud, string exp, string nbf, string scopes,
            string client_notification_token, string binding_message,
            string user_code, string requested_expiry, string login_hint,
            Dictionary <string, object> requestContextAndIntent,
            string ecdsaX509FilePath, string ecdsaX509Password)
        ///// <param name="ecPrivateKey">ES256用のECParameters秘密鍵</param>
        //ECParameters ecPrivateKey) // ECDsa.ExportParameters(true)が動かねぇ。
        {
            string json = "";

            #region ClaimSetの生成

            Dictionary <string, object> requestObjectClaimSet = new Dictionary <string, object>();

            requestObjectClaimSet.Add(OAuth2AndOIDCConst.iss, iss); // client_id
            requestObjectClaimSet.Add(OAuth2AndOIDCConst.aud, aud); // ROS EndPointのuri。
            requestObjectClaimSet.Add(OAuth2AndOIDCConst.exp, exp);
            requestObjectClaimSet.Add(OAuth2AndOIDCConst.iat, CmnJwtToken.CreateIatClaim());
            requestObjectClaimSet.Add(OAuth2AndOIDCConst.nbf, nbf);
            requestObjectClaimSet.Add(OAuth2AndOIDCConst.jti, CmnJwtToken.CreateJitClaim());

            requestObjectClaimSet.Add(OAuth2AndOIDCConst.scope, scopes);
            requestObjectClaimSet.Add(OAuth2AndOIDCConst.client_notification_token, client_notification_token);
            requestObjectClaimSet.Add(OAuth2AndOIDCConst.binding_message, binding_message);

            if (!string.IsNullOrEmpty(user_code))
            {
                requestObjectClaimSet.Add(OAuth2AndOIDCConst.user_code, user_code);
            }
            if (!string.IsNullOrEmpty(requested_expiry))
            {
                requestObjectClaimSet.Add(OAuth2AndOIDCConst.requested_expiry, requested_expiry);
            }

            requestObjectClaimSet.Add(OAuth2AndOIDCConst.login_hint, login_hint);

            if (requestContextAndIntent != null)
            {
                foreach (string key in requestContextAndIntent.Keys)
                {
                    requestObjectClaimSet.Add(key, requestContextAndIntent[key]);
                }
            }

            json = JsonConvert.SerializeObject(requestObjectClaimSet);

            #endregion

            #region JWT化

            JWS_ES256_X509 jwtES256 = new JWS_ES256_X509(ecdsaX509FilePath, ecdsaX509Password);
            return(jwtES256.Create(json));

            #endregion
        }
        // AuthZに実装(パラメタ体系が違うため)
        #endregion

        #region Verify
        /// <summary>汎用認証サイトの発行したResponseObjectを検証する。</summary>
        /// <param name="response">string</param>
        /// <param name="jobj">out JObject</param>
        /// <returns>検証結果</returns>
        public static bool Verify(string response, out JObject jobj)
        {
            // JWS検証
            string jwtPayload = "";

            if (CmnJwtToken.Verify(response, out jwtPayload))
            {
                jobj = ((JObject)JsonConvert.DeserializeObject(jwtPayload));

                #region クレーム検証

                if (jobj.ContainsKey(OAuth2AndOIDCConst.error))
                {
                    // errorの場合
                    return(true);
                }
                else
                {
                    // errorでない場合

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

                    long unixTimeSeconds = 0;
#if NET45
                    unixTimeSeconds = PubCmnFunction.ToUnixTime(DateTimeOffset.Now);
#else
                    unixTimeSeconds = DateTimeOffset.Now.ToUnixTimeSeconds();
#endif

                    if (iss == CmnClientParams.Isser &&
                        long.Parse(exp) >= unixTimeSeconds)
                    {
                        if (string.IsNullOrEmpty(OAuth2AndOIDCParams.JwkSetFilePath))
                        {
                            // Client側
                            if (aud == OAuth2AndOIDCParams.ClientID)
                            {
                                // OAuth2 Clientバージョンの実装で成功
                                return(true);
                            }
                            else if (OAuth2AndOIDCParams.ClientIDs.Any(x => x == aud))
                            {
                                // OAuth2 ResourcesServerバージョンの実装で成功
                                return(true);
                            }
                            else
                            {
                                // JWTの内容検証に失敗
                            }
                        }
                        else
                        {
                            // AuthZ側(検証用カバレッジ
                            // OAuth2 AuthZバージョンの実装で成功
                            return(true);
                        }
                    }
                    else
                    {
                        // JWTの内容検証に失敗
                    }
                }

                #endregion
            }
            else
            {
                // JWTの署名検証に失敗
                jobj = null;
            }

            // 認証に失敗
            return(false);
        }
        // AuthZに実装(パラメタ体系が違うため)
        #endregion

        #region Verify

        /// <summary>汎用認証サイトの発行したIdTokenを検証する。</summary>
        /// <param name="id_token">string</param>
        /// <param name="access_token">string</param>
        /// <param name="code">string</param>
        /// <param name="state">string</param>
        /// <param name="sub">out string</param>
        /// <param name="nonce">out string</param>
        /// <param name="jobj">out JObject</param>
        /// <returns>検証結果</returns>
        public static bool Verify(string id_token,
                                  string access_token, string code, string state,
                                  out string sub, out string nonce, out JObject jobj)
        {
            sub   = "";
            nonce = "";
            jobj  = null;

            // JWS検証
            string jwtPayload = "";

            if (CmnJwtToken.Verify(id_token, out jwtPayload))
            {
                jobj = ((JObject)JsonConvert.DeserializeObject(jwtPayload));

                #region クレーム検証

                // out
                sub   = (string)jobj[OAuth2AndOIDCConst.sub];
                nonce = (string)jobj[OAuth2AndOIDCConst.nonce];

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

                #region ハッシュ・クレーム検証

                // at_hash
                string at_hash = (string)jobj[OAuth2AndOIDCConst.at_hash];
                if (!string.IsNullOrEmpty(access_token) && !string.IsNullOrEmpty(at_hash))
                {
                    if (!IdToken.VerifyHash(access_token, at_hash))
                    {
                        return(false);
                    }
                }

                // c_hash
                string c_hash = (string)jobj[OAuth2AndOIDCConst.c_hash];
                if (!string.IsNullOrEmpty(code) && !string.IsNullOrEmpty(c_hash))
                {
                    if (!IdToken.VerifyHash(code, c_hash))
                    {
                        return(false);
                    }
                }

                // s_hash
                string s_hash = (string)jobj[OAuth2AndOIDCConst.s_hash];
                if (!string.IsNullOrEmpty(state) && !string.IsNullOrEmpty(s_hash))
                {
                    if (!IdToken.VerifyHash(state, s_hash))
                    {
                        return(false);
                    }
                }

                #endregion

                long unixTimeSeconds = 0;

#if NET45
                unixTimeSeconds = PubCmnFunction.ToUnixTime(DateTimeOffset.Now);
#else
                unixTimeSeconds = DateTimeOffset.Now.ToUnixTimeSeconds();
#endif

                if (iss == CmnClientParams.Isser &&
                    long.Parse(exp) >= unixTimeSeconds)
                {
                    if (string.IsNullOrEmpty(OAuth2AndOIDCParams.JwkSetFilePath))
                    {
                        // Client側
                        if (aud == OAuth2AndOIDCParams.ClientID)
                        {
                            // OAuth2 Clientバージョンの実装で成功
                            return(true);
                        }
                        else if (OAuth2AndOIDCParams.ClientIDs.Any(x => x == aud))
                        {
                            // OAuth2 ResourcesServerバージョンの実装で成功
                            return(true);
                        }
                        else
                        {
                            // JWTの内容検証に失敗
                        }
                    }
                    else
                    {
                        // AuthZ側(検証用カバレッジ
                        // OAuth2 AuthZバージョンの実装で成功
                        return(true);
                    }
                }
                else
                {
                    // JWTの内容検証に失敗
                }

                #endregion
            }
            else
            {
                // JWTの署名検証に失敗
            }

            // 認証に失敗
            return(false);
        }
        // AuthZに実装(パラメタ体系が違うため)
        #endregion

        #region Verify
        /// <summary>汎用認証サイトの発行したAccessTokenを検証する。</summary>
        /// <param name="access_token">
        /// AccessTokenで以下の項目が必要
        ///  - iss
        ///  - aud
        ///  - iat
        ///  - exp
        ///  - sub
        ///  - roles  (option)
        ///  - scopes (option)
        ///  - その他 (option)
        /// </param>
        /// <param name="sub">out string</param>
        /// <param name="roles">out List(string)</param>
        /// <param name="scopes">out List(string)</param>
        /// <param name="jobj">out JObject</param>
        /// <returns>検証結果</returns>
        public static bool Verify(string access_token,
                                  out string sub, out List <string> roles, out List <string> scopes, out JObject jobj)
        {
            sub    = "";
            roles  = new List <string>();
            scopes = new List <string>();
            jobj   = null;

            // JWS検証
            string jwtPayload = "";

            if (CmnJwtToken.Verify(access_token, out jwtPayload))
            {
                jobj = ((JObject)JsonConvert.DeserializeObject(jwtPayload));

                #region クレーム検証

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

                sub = (string)jobj[OAuth2AndOIDCConst.sub];

                if (jobj[OAuth2AndOIDCConst.Scope_Roles] != null)
                {
                    roles = JsonConvert.DeserializeObject <List <string> >(jobj[OAuth2AndOIDCConst.Scope_Roles].ToString());
                }
                if (jobj[OAuth2AndOIDCConst.scopes] != null)
                {
                    scopes = JsonConvert.DeserializeObject <List <string> >(jobj[OAuth2AndOIDCConst.scopes].ToString());
                }

                long unixTimeSeconds = 0;
#if NET45
                unixTimeSeconds = PubCmnFunction.ToUnixTime(DateTimeOffset.Now);
#else
                unixTimeSeconds = DateTimeOffset.Now.ToUnixTimeSeconds();
#endif

                if (iss == CmnClientParams.Isser &&
                    long.Parse(exp) >= unixTimeSeconds)
                {
                    if (string.IsNullOrEmpty(OAuth2AndOIDCParams.JwkSetFilePath))
                    {
                        // Client側
                        if (aud == OAuth2AndOIDCParams.ClientID)
                        {
                            // OAuth2 Clientバージョンの実装で成功
                            return(true);
                        }
                        else if (OAuth2AndOIDCParams.ClientIDs.Any(x => x == aud))
                        {
                            // OAuth2 ResourcesServerバージョンの実装で成功
                            return(true);
                        }
                        else
                        {
                            // JWTの内容検証に失敗
                        }
                    }
                    else
                    {
                        // AuthZ側(検証用カバレッジ
                        // OAuth2 AuthZバージョンの実装で成功
                        return(true);
                    }
                }
                else
                {
                    // JWTの内容検証に失敗
                }

                #endregion
            }
            else
            {
                // JWTの署名検証に失敗
            }

            // 認証に失敗
            return(false);
        }