/// <summary> /// ProtectFromAccessTokenPayload /// Hybrid Flow対応(access_token_payloadを処理) /// </summary> /// <param name="access_token_payload">AccessTokenのPayload</param> /// <param name="customExp">Hybrid Flowのtokenに対応したexp</param> /// <returns>IdToken</returns> public static string ProtectFromAccessTokenPayload(string access_token_payload, ulong customExp) { string json = ""; //string jws = ""; // ticketの値を使用(これは、codeのexpっぽい。300秒になっているのでNG。) //authTokenClaimSet.Add(OAuth2AndOIDCConst.exp, ticket.Properties.ExpiresUtc.Value.ToUnixTimeSeconds().ToString()); //authTokenClaimSet.Add(OAuth2AndOIDCConst.exp, DateTimeOffset.Now.AddSeconds(customExp).ToUnixTimeSeconds().ToString()); #region JSON編集 // access_token_payloadのDictionary化 Dictionary <string, object> payload = JsonConvert.DeserializeObject <Dictionary <string, object> >(access_token_payload); // ★ customExpの値を使用する。 payload[OAuth2AndOIDCConst.exp] = DateTimeOffset.Now.AddSeconds(customExp).ToUnixTimeSeconds().ToString(); // ★ Hybrid Flow対応なので、scopeを制限してもイイ。 payload[OAuth2AndOIDCConst.scopes] = payload[OAuth2AndOIDCConst.scopes]; json = JsonConvert.SerializeObject(payload); #endregion #region JWS化 JWS_RS256_X509 jwsRS256 = null; // 署名 jwsRS256 = new JWS_RS256_X509(ASPNETIdentityConfig.OAuth2JWT_pfx, ASPNETIdentityConfig.OAuth2JWTPassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); // JWSHeaderのセット // kid : https://openid-foundation-japan.github.io/rfc7638.ja.html#Example Dictionary <string, string> jwk = JsonConvert.DeserializeObject <Dictionary <string, string> >( RS256_KeyConverter.X509PfxToJwkPublicKey(ASPNETIdentityConfig.OAuth2JWT_pfx, ASPNETIdentityConfig.OAuth2JWTPassword)); jwsRS256.JWSHeader.kid = jwk[JwtConst.kid]; jwsRS256.JWSHeader.jku = ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + OAuth2AndOIDCParams.JwkSetUri; return(jwsRS256.Create(json)); //// 検証 //jwsRS256 = new JWS_RS256_X509(OAuth2AndOIDCParams.RS256Cer, ASPNETIdentityConfig.OAuth2JWTPassword, // X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); //if (jwsRS256.Verify(jws)) //{ // return jws; // 検証できた。 //} //else //{ // return ""; // 検証できなかった。 //} #endregion }
static void Main(string[] args) { // 現在の証明書のJwk JObject jwkObject = JsonConvert.DeserializeObject <JObject>( RS256_KeyConverter.X509CerToJwkPublicKey(OAuth2AndOIDCParams.RS256Cer)); // JwkSet.jsonファイルの存在チェック if (!ResourceLoader.Exists(OAuth2AndOIDCParams.JwkSetFilePath, false)) { // 新規 File.Create(OAuth2AndOIDCParams.JwkSetFilePath).Close(); } else { // 既存? } // JwkSet.jsonファイルのロード JwkSet jwkSetObject = JwkSet.LoadJwkSet(OAuth2AndOIDCParams.JwkSetFilePath); // 判定 if (jwkSetObject == null) { // 新規 jwkSetObject = new JwkSet(); jwkSetObject.keys.Add(jwkObject); } else { // 既存 // kidの重複確認 JwkSet.AddJwkToJwkSet(jwkSetObject, jwkObject); } // jwkSetObjectのセーブ JwkSet.SaveJwkSet(OAuth2AndOIDCParams.JwkSetFilePath, jwkSetObject); }
/// <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); } }
/// <summary>JWT検証</summary> private void btnJWTVerify_Click(object sender, EventArgs e) { bool ret = false; if (rbnJWTHS256.Checked) { // HS256 // 入力 string[] temp = this.txtJWTSign.Text.Split('.'); // 改変可能なフィールドから入力 string newJWT = CustomEncode.ToBase64UrlString(CustomEncode.StringToByte(this.txtJWTHeader.Text, CustomEncode.UTF_8)) + "." + CustomEncode.ToBase64UrlString(CustomEncode.StringToByte(this.txtJWTPayload.Text, CustomEncode.UTF_8)) + "." + temp[2]; // 検証 //JWT_HS256 jwtHS256 = new JWT_HS256(CustomEncode.StringToByte(this.txtJWTKey.Text, CustomEncode.UTF_8)); JWT_HS256 jwtHS256 = new JWT_HS256(this.txtJWTJWK.Text); ret = jwtHS256.Verify(newJWT); } else if (rbnJWTRS256_XML.Checked) { // RS256 (XML) // 入力 string[] temp = this.txtJWTSign.Text.Split('.'); // 改変可能なフィールドから入力 string newJWT = CustomEncode.ToBase64UrlString(CustomEncode.StringToByte(this.txtJWTHeader.Text, CustomEncode.UTF_8)) + "." + CustomEncode.ToBase64UrlString(CustomEncode.StringToByte(this.txtJWTPayload.Text, CustomEncode.UTF_8)) + "." + temp[2]; // 検証 JWT_RS256_XML jwtRS256 = new JWT_RS256_XML(this.txtJWTKey.Text); ret = jwtRS256.Verify(newJWT); } else if (rbnJWTRS256_Param.Checked) { // RS256 (Param) // 入力 string[] temp = this.txtJWTSign.Text.Split('.'); // 改変可能なフィールドから入力 string newJWT = CustomEncode.ToBase64UrlString(CustomEncode.StringToByte(this.txtJWTHeader.Text, CustomEncode.UTF_8)) + "." + CustomEncode.ToBase64UrlString(CustomEncode.StringToByte(this.txtJWTPayload.Text, CustomEncode.UTF_8)) + "." + temp[2]; // 検証 //JWT_RS256_Param jwtRS256 = new JWT_RS256_Param( // RS256_KeyConverter.XmlToProvider(this.txtJWTKey.Text).ExportParameters(false)); JWT_RS256_Param jwtRS256 = new JWT_RS256_Param( RS256_KeyConverter.JwkToProvider(this.txtJWTJWK.Text).ExportParameters(false)); ret = jwtRS256.Verify(newJWT); } else { // RS256 (X509) // 入力 string[] temp = this.txtJWTSign.Text.Split('.'); // 改変可能なフィールドから入力 string newJWT = CustomEncode.ToBase64UrlString(CustomEncode.StringToByte(this.txtJWTHeader.Text, CustomEncode.UTF_8)) + "." + CustomEncode.ToBase64UrlString(CustomEncode.StringToByte(this.txtJWTPayload.Text, CustomEncode.UTF_8)) + "." + temp[2]; // 検証 JWT_RS256_X509 jwtRS256 = new JWT_RS256_X509(this.CertificateFilePath_cer, ""); ret = jwtRS256.Verify(newJWT); } if (ret) { MessageBox.Show("検証成功"); } else { MessageBox.Show("検証失敗"); } }
/// <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>Protect</summary> /// <param name="ticket">AuthenticationTicket</param> /// <returns>JWT文字列</returns> public string Protect(AuthenticationTicket ticket) { string json = ""; //string jws = ""; // チェック if (ticket == null) { throw new ArgumentNullException("ticket"); } ApplicationUserManager userManager = HttpContext.Current.GetOwinContext().GetUserManager <ApplicationUserManager>(); ApplicationUser user = null; if (ticket.Identity.Name == null) { // Client認証の場合、 user = null; } else { // Resource Owner認証の場合、 user = userManager.FindByName(ticket.Identity.Name); // 同期版でOK。 } #region ClaimSetの生成 Dictionary <string, object> authTokenClaimSet = new Dictionary <string, object>(); List <string> scopes = new List <string>(); List <string> roles = new List <string>(); foreach (Claim c in ticket.Identity.Claims) { if (c.Type == OAuth2AndOIDCConst.Claim_Issuer) { authTokenClaimSet.Add(OAuth2AndOIDCConst.iss, c.Value); } else if (c.Type == OAuth2AndOIDCConst.Claim_Audience) { authTokenClaimSet.Add(OAuth2AndOIDCConst.aud, c.Value); } else if (c.Type == OAuth2AndOIDCConst.Claim_Nonce) { authTokenClaimSet.Add(OAuth2AndOIDCConst.nonce, c.Value); } else if (c.Type == OAuth2AndOIDCConst.Claim_Scopes) { scopes.Add(c.Value); } else if (c.Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/role") { roles.Add(c.Value); } } if (ticket.Identity.Name == null) { // Client認証の場合、aud(client_id)に対応するClient名称 authTokenClaimSet.Add(OAuth2AndOIDCConst.sub, OAuth2Helper.GetInstance().GetClientName((string)authTokenClaimSet[OAuth2AndOIDCConst.aud])); } else { // Resource Owner認証の場合、Resource Ownerの名称 authTokenClaimSet.Add(OAuth2AndOIDCConst.sub, ticket.Identity.Name); } authTokenClaimSet.Add(OAuth2AndOIDCConst.exp, ticket.Properties.ExpiresUtc.Value.ToUnixTimeSeconds().ToString()); authTokenClaimSet.Add(OAuth2AndOIDCConst.nbf, DateTimeOffset.Now.ToUnixTimeSeconds().ToString()); authTokenClaimSet.Add(OAuth2AndOIDCConst.iat, ticket.Properties.IssuedUtc.Value.ToUnixTimeSeconds().ToString()); authTokenClaimSet.Add(OAuth2AndOIDCConst.jti, Guid.NewGuid().ToString("N")); authTokenClaimSet.Add(OAuth2AndOIDCConst.scopes, scopes); // scope値によって、返す値を変更する。 foreach (string scope in scopes) { if (user != null) { // user == null では NG な Resource(Resource Owner の Resource) switch (scope.ToLower()) { #region OpenID Connect case OAuth2AndOIDCConst.Scope_Profile: // ・・・ break; case OAuth2AndOIDCConst.Scope_Email: authTokenClaimSet.Add(OAuth2AndOIDCConst.Scope_Email, user.Email); authTokenClaimSet.Add(OAuth2AndOIDCConst.email_verified, user.EmailConfirmed.ToString()); break; case OAuth2AndOIDCConst.Scope_Phone: authTokenClaimSet.Add(OAuth2AndOIDCConst.phone_number, user.PhoneNumber); authTokenClaimSet.Add(OAuth2AndOIDCConst.phone_number_verified, user.PhoneNumberConfirmed.ToString()); break; case OAuth2AndOIDCConst.Scope_Address: // ・・・ break; #endregion #region Else case OAuth2AndOIDCConst.Scope_UserID: authTokenClaimSet.Add(OAuth2AndOIDCConst.Scope_UserID, user.Id); break; case OAuth2AndOIDCConst.Scope_Roles: authTokenClaimSet.Add( OAuth2AndOIDCConst.Scope_Roles, userManager.GetRolesAsync(user.Id).Result); break; #endregion } } else { // user == null でも OK な Resource } } json = JsonConvert.SerializeObject(authTokenClaimSet); #endregion #region JWS化 JWS_RS256_X509 jwsRS256 = null; // JWT_RS256_X509 jwsRS256 = new JWS_RS256_X509(ASPNETIdentityConfig.OAuth2JWT_pfx, ASPNETIdentityConfig.OAuth2JWTPassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); // JWSHeaderのセット // kid : https://openid-foundation-japan.github.io/rfc7638.ja.html#Example Dictionary <string, string> jwk = JsonConvert.DeserializeObject <Dictionary <string, string> >( RS256_KeyConverter.X509PfxToJwkPublicKey(ASPNETIdentityConfig.OAuth2JWT_pfx, ASPNETIdentityConfig.OAuth2JWTPassword)); jwsRS256.JWSHeader.kid = jwk[JwtConst.kid]; jwsRS256.JWSHeader.jku = ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + OAuth2AndOIDCParams.JwkSetUri; // 署名 return(jwsRS256.Create(json)); //// 検証 //jwsRS256 = new JWS_RS256_X509(OAuth2AndOIDCParams.RS256Cer, ASPNETIdentityConfig.OAuth2JWTPassword, // X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); //if (jwsRS256.Verify(jws)) //{ // return jws; // 検証できた。 //} //else //{ // return ""; // 検証できなかった。 //} #endregion }
/// <summary>Unprotect</summary> /// <param name="jwt">JWT文字列</param> /// <returns>AuthenticationTicket</returns> public AuthenticationTicket Unprotect(string jwt) { // 空のケースあり。 if (string.IsNullOrEmpty(jwt)) { return(null); } // 検証 JWS_RS256 jwsRS256 = null; // 証明書を使用するか、Jwkを使用するか判定 Dictionary <string, string> header = JsonConvert.DeserializeObject <Dictionary <string, string> >( CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(jwt.Split('.')[0]), CustomEncode.UTF_8)); if (header.Keys.Any(s => s == JwtConst.kid)) { if (string.IsNullOrEmpty(header[JwtConst.kid])) { // 証明書を使用 jwsRS256 = new JWS_RS256_X509(OAuth2AndOIDCParams.RS256Cer, ""); } else { JwkSet jwkSetObject = JwkSet.LoadJwkSet(OAuth2AndOIDCParams.JwkSetFilePath); JObject jwkObject = JwkSet.GetJwkObject(jwkSetObject, header[JwtConst.kid]); if (jwkObject == null) { // 証明書を使用 jwsRS256 = new JWS_RS256_X509(OAuth2AndOIDCParams.RS256Cer, ""); } else { // Jwkを使用 jwsRS256 = new JWS_RS256_Param( RS256_KeyConverter.JwkToProvider(jwkObject).ExportParameters(false)); } } } if (jwsRS256.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[OAuth2AndOIDCConst.jti]); if (datetime == null) { // authToken.iss, authToken.expの検証 if ((string)authTokenClaimSet[OAuth2AndOIDCConst.iss] == ASPNETIdentityConfig.OAuth2IssuerId && OAuth2Helper.GetInstance().GetClientSecret((string)authTokenClaimSet[OAuth2AndOIDCConst.aud]) != null && long.Parse((string)authTokenClaimSet[OAuth2AndOIDCConst.exp]) >= DateTimeOffset.Now.ToUnixTimeSeconds()) { // authToken.subの検証 // ApplicationUser を取得する。 ApplicationUserManager userManager = HttpContext.Current.GetOwinContext().GetUserManager <ApplicationUserManager>(); ApplicationUser user = userManager.FindByName((string)authTokenClaimSet[OAuth2AndOIDCConst.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[OAuth2AndOIDCConst.scopes]) { scopes.Add(s); } OAuth2Helper.AddClaim(identity, (string)authTokenClaimSet[OAuth2AndOIDCConst.aud], "", scopes, (string) authTokenClaimSet[OAuth2AndOIDCConst.nonce]); // その他、所定のClaimを追加する。 identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_ExpirationTime, (string)authTokenClaimSet[OAuth2AndOIDCConst.exp])); identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_NotBefore, (string)authTokenClaimSet[OAuth2AndOIDCConst.nbf])); identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_IssuedAt, (string)authTokenClaimSet[OAuth2AndOIDCConst.iat])); identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_JwtId, (string)authTokenClaimSet[OAuth2AndOIDCConst.jti])); // AuthenticationPropertiesの生成 AuthenticationProperties prop = new AuthenticationProperties(); prop.IssuedUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet[OAuth2AndOIDCConst.iat])); prop.ExpiresUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet[OAuth2AndOIDCConst.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[OAuth2AndOIDCConst.sub] == OAuth2Helper.GetInstance().GetClientName((string)authTokenClaimSet[OAuth2AndOIDCConst.aud])) { // ClaimsIdentityを生成し、 ClaimsIdentity identity = new ClaimsIdentity(DefaultAuthenticationTypes.ExternalBearer); // sub(client_idに対応するclient_name)Claimを設定する。 identity.AddClaim(new Claim(ClaimTypes.Name, (string)authTokenClaimSet[OAuth2AndOIDCConst.sub])); // aud、scopes、nonceなどのClaimを追加する。 List <string> scopes = new List <string>(); foreach (string s in (JArray)authTokenClaimSet[OAuth2AndOIDCConst.scopes]) { scopes.Add(s); } OAuth2Helper.AddClaim(identity, (string)authTokenClaimSet[OAuth2AndOIDCConst.aud], "", scopes, (string)authTokenClaimSet[OAuth2AndOIDCConst.nonce]); // その他、所定のClaimを追加する。 identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_ExpirationTime, (string)authTokenClaimSet[OAuth2AndOIDCConst.exp])); identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_NotBefore, (string)authTokenClaimSet[OAuth2AndOIDCConst.nbf])); identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_IssuedAt, (string)authTokenClaimSet[OAuth2AndOIDCConst.iat])); identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_JwtId, (string)authTokenClaimSet[OAuth2AndOIDCConst.jti])); // AuthenticationPropertiesの生成 AuthenticationProperties prop = new AuthenticationProperties(); prop.IssuedUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet[OAuth2AndOIDCConst.iat])); prop.ExpiresUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet[OAuth2AndOIDCConst.exp])); AuthenticationTicket auth = new AuthenticationTicket(identity, prop); // 認証結果を返す。 return(auth); } } } else { // クレーム検証の失敗 } } else { // 取り消し済み } } else { // JWT署名検証の失敗 } // 検証、認証ナドナド、できなかった。 return(null); }