/// <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); } }
/// <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); } }
/// <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); } }
/// <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); } }
/// <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)); }
/// <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); } }
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; } }
/// <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); } }
/// <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")); }
/// <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(""); }
/// <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); } }
/// <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); }
//[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); // 失敗 }
//[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); // 失敗 }
//[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); // 失敗 }
/// <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(""); }
/// <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)); }
/// <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); } }
/// <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); } }
/// <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); }
/// <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); }
/// <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)); }
/// <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); } } } }