/// <summary> /// Adds a specific <see cref="X509Certificate2"/> to decrypt /// authorization requests received by the OpenID Connect server. /// </summary> /// <param name="credentials">The options used to configure the OpenID Connect server.</param> /// <param name="certificate">The certificate used to decrypt authorization requests received by the server.</param> /// <returns>The encryption credentials.</returns> public static IList <EncryptingCredentials> AddCertificate( [NotNull] this IList <EncryptingCredentials> credentials, [NotNull] X509Certificate2 certificate) { if (credentials == null) { throw new ArgumentNullException(nameof(credentials)); } if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } if (certificate.PrivateKey == null) { throw new InvalidOperationException("The certificate doesn't contain the required private key."); } var identifier = new SecurityKeyIdentifier { new X509IssuerSerialKeyIdentifierClause(certificate), new X509RawDataKeyIdentifierClause(certificate), new X509ThumbprintKeyIdentifierClause(certificate), new LocalIdKeyIdentifierClause(certificate.Thumbprint.ToUpperInvariant()) }; // Mark the security key identifier as read-only to // ensure it can't be altered during a request. identifier.MakeReadOnly(); credentials.Add(new X509EncryptingCredentials(certificate, identifier)); return(credentials); }
public void ReadOnlyAdd() { SecurityKeyIdentifier ki = new SecurityKeyIdentifier(); ki.MakeReadOnly(); ki.Add(new LocalIdKeyIdentifierClause("foo")); }
/// <summary> /// Adds a specific <see cref="X509Certificate2"/> to sign the tokens issued by the OpenID Connect server. /// </summary> /// <param name="credentials">The options used to configure the OpenID Connect server.</param> /// <param name="certificate">The certificate used to sign security tokens issued by the server.</param> /// <returns>The signing credentials.</returns> public static IList <SigningCredentials> AddCertificate( [NotNull] this IList <SigningCredentials> credentials, [NotNull] X509Certificate2 certificate) { if (credentials == null) { throw new ArgumentNullException(nameof(credentials)); } if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } if (certificate.NotBefore > DateTime.Now) { throw new InvalidOperationException("The specified certificate is not yet valid."); } if (certificate.NotAfter < DateTime.Now) { throw new InvalidOperationException("The specified certificate is no longer valid."); } if (!certificate.HasPrivateKey) { throw new InvalidOperationException("The specified certificate doesn't contain the required private key."); } var identifier = new SecurityKeyIdentifier { new X509IssuerSerialKeyIdentifierClause(certificate), new X509RawDataKeyIdentifierClause(certificate), new X509ThumbprintKeyIdentifierClause(certificate), new LocalIdKeyIdentifierClause(certificate.Thumbprint.ToUpperInvariant()), new NamedKeySecurityKeyIdentifierClause(JwtHeaderParameterNames.X5t, certificate.Thumbprint.ToUpperInvariant()) }; // Mark the security key identifier as read-only to // ensure it can't be altered during a request. identifier.MakeReadOnly(); credentials.Add(new X509SigningCredentials(certificate, identifier)); return(credentials); }
/// <summary> /// Adds a specific <see cref="SecurityKey"/> to sign tokens issued by the OpenID Connect server. /// </summary> /// <param name="credentials">The options used to configure the OpenID Connect server.</param> /// <param name="key">The key used to sign security tokens issued by the server.</param> /// <returns>The signing credentials.</returns> public static IList <SigningCredentials> AddKey( [NotNull] this IList <SigningCredentials> credentials, [NotNull] SecurityKey key) { if (credentials == null) { throw new ArgumentNullException(nameof(credentials)); } if (key == null) { throw new ArgumentNullException(nameof(key)); } if (key.IsSupportedAlgorithm(SecurityAlgorithms.RsaSha256Signature)) { var x509SecurityKey = key as X509SecurityKey; if (x509SecurityKey != null) { return(credentials.AddCertificate(x509SecurityKey.Certificate)); } var x509AsymmetricSecurityKey = key as X509AsymmetricSecurityKey; if (x509AsymmetricSecurityKey != null) { // The X.509 certificate is not directly accessible when using X509AsymmetricSecurityKey. // Reflection is the only way to get the certificate used to create the security key. var field = typeof(X509AsymmetricSecurityKey).GetField( name: "certificate", bindingAttr: BindingFlags.Instance | BindingFlags.NonPublic); Debug.Assert(field != null); return(credentials.AddCertificate((X509Certificate2)field.GetValue(x509AsymmetricSecurityKey))); } // Create an empty security key identifier. var identifier = new SecurityKeyIdentifier(); var rsaSecurityKey = key as RsaSecurityKey; if (rsaSecurityKey != null) { // Resolve the underlying algorithm from the security key. var algorithm = (RSA)rsaSecurityKey.GetAsymmetricAlgorithm( algorithm: SecurityAlgorithms.RsaSha256Signature, requiresPrivateKey: false); Debug.Assert(algorithm != null, "SecurityKey.GetAsymmetricAlgorithm() shouldn't return a null algorithm."); // Export the RSA public key to extract a key identifier based on the modulus component. var parameters = algorithm.ExportParameters(includePrivateParameters: false); Debug.Assert(parameters.Modulus != null, "RSA.ExportParameters() shouldn't return a null modulus."); // Only use the 40 first chars of the base64url-encoded modulus. var kid = Base64UrlEncoder.Encode(parameters.Modulus); kid = kid.Substring(0, Math.Min(kid.Length, 40)).ToUpperInvariant(); identifier.Add(new RsaKeyIdentifierClause(algorithm)); identifier.Add(new LocalIdKeyIdentifierClause(kid)); } // Mark the security key identifier as read-only to // ensure it can't be altered during a request. identifier.MakeReadOnly(); credentials.Add(new SigningCredentials(key, SecurityAlgorithms.RsaSha256Signature, SecurityAlgorithms.Sha256Digest, identifier)); return(credentials); } else if (key.IsSupportedAlgorithm(SecurityAlgorithms.HmacSha256Signature)) { // When using an in-memory symmetric key, no identifier clause can be inferred from the key itself. // To prevent the built-in security token handlers from throwing an exception, a default identifier is added. var identifier = new SecurityKeyIdentifier(new LocalIdKeyIdentifierClause("Default")); // Mark the security key identifier as read-only to // ensure it can't be altered during a request. identifier.MakeReadOnly(); credentials.Add(new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature, SecurityAlgorithms.Sha256Digest, identifier)); return(credentials); } throw new InvalidOperationException("A signature algorithm cannot be automatically inferred from the signing key. " + "Consider using 'options.SigningCredentials.Add(SigningCredentials)' instead."); }
public void ReadOnlyAdd () { SecurityKeyIdentifier ki = new SecurityKeyIdentifier (); ki.MakeReadOnly (); ki.Add (new LocalIdKeyIdentifierClause ("foo")); }