/// <summary> /// Dispose all resources. /// </summary> /// <param name="disposing">If true, dispose both managed and unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (disposing) { openid = null; _SessionManager = null; _AssociationManager = null; } if (listener != null) { listener.Close(); } }
/// <summary> /// Enable Stateful authentication mode using supplied /// association and session persistence plug-ins. /// </summary> /// <param name="associationManager">IAssociationPersistence object to use while persisting associations from OpenID Providers.</param> /// <param name="sessionManager">ISessionPersistence object to use while persisting user session state.</param> public void EnableStatefulMode(IAssociationPersistence associationManager, ISessionPersistence sessionManager) { if (associationManager == null) { throw new ArgumentNullException("associationManager"); } if (sessionManager == null) { throw new ArgumentNullException("sessionManager"); } StateContainer.AssociationManager = associationManager; StateContainer.SessionManager = sessionManager; StateContainer.AuthMode = AuthenticationMode.Stateful; StateContainer.AssociationManager.Cleanup(); }
/// <summary> /// Enable Stateful authentication using default (volatile) persistence objects. /// </summary> /// <remarks> /// Uses <see cref="SingularAssociationManager"/> and <see cref="SingularSessionManager"/> /// objects. These are volatile, and all contained data will be destroyed when /// the <see cref="OpenIdDesktopClient"/> object is disposed. /// </remarks> public void EnableStatefulMode() { _StatefulMode = true; _AssociationManager = new SingularAssociationManager(); _SessionManager = new SingularSessionManager(); openid.EnableStatefulMode(_AssociationManager, _SessionManager); }
/// <summary> /// Enable Stateful authentication using supplied persistence objects. /// </summary> /// <param name="associationManager">IAssociationPersistence object to use when persisting associations.</param> /// <param name="sessionManager">ISessionPersistence object to use when persisting per-user data.</param> public void EnableStatefulMode(IAssociationPersistence associationManager, ISessionPersistence sessionManager) { if (associationManager == null) { throw new ArgumentNullException("associationManager"); } if (sessionManager == null) { throw new ArgumentNullException("sessionManager"); } _StatefulMode = true; _AssociationManager = associationManager; _SessionManager = sessionManager; openid.EnableStatefulMode(_AssociationManager, _SessionManager); }
/// <summary> /// Creates a new StateContainer. /// </summary> /// <param name="associationManager">Association persistence manager.</param> /// <param name="sessionManager">Session persistence manager.</param> public StateContainer(IAssociationPersistence associationManager, ISessionPersistence sessionManager) { AssociationManager = associationManager; SessionManager = sessionManager; }
/// <summary> /// Perform an association request with an OpenID Provider. /// </summary> /// <param name="server">URL to the OpenID Provider.</param> /// <param name="associationManager">The IAssociationPersistence object to use for persistence.</param> /// <param name="version">The ProtocolVersion to use.</param> /// <param name="encryption">The key encryption type to use.</param> /// <returns>Populated Association object, or null.</returns> internal static Association CreateAssociation(Uri server, IAssociationPersistence associationManager, ProtocolVersion version, KeyEncryption encryption) { if (server == null) { throw new ArgumentNullException("server"); } if (associationManager == null) { throw new ArgumentNullException("associationManager"); } NameValueCollection sd = new NameValueCollection(); DiffieHellmanManaged dhm = new DiffieHellmanManaged(); sd["openid.mode"] = "associate"; switch (version) { case ProtocolVersion.V2Dot0: sd["openid.ns"] = ProtocolUri.OpenId2Dot0.AbsoluteUri; break; case ProtocolVersion.V1Dot1: if (encryption == KeyEncryption.DHSHA256) { encryption = KeyEncryption.DHSHA1; } break; } byte[] pubkey = null; DHParameters dp; switch (encryption) { case KeyEncryption.None: sd["openid.assoc_type"] = "HMAC-SHA1"; switch (version) { case ProtocolVersion.V2Dot0: sd["openid.session_type"] = "no-encryption"; break; case ProtocolVersion.V1Dot1: sd["openid.session_type"] = ""; break; } break; case KeyEncryption.DHSHA1: pubkey = dhm.CreateKeyExchange(); dp = dhm.ExportParameters(true); sd["openid.assoc_type"] = "HMAC-SHA1"; sd["openid.session_type"] = "DH-SHA1"; sd["openid.dh_modulus"] = Utility.UnsignedToBase64(dp.P); sd["openid.dh_gen"] = Utility.UnsignedToBase64(dp.G); sd["openid.dh_consumer_public"] = Utility.UnsignedToBase64(pubkey); break; case KeyEncryption.DHSHA256: pubkey = dhm.CreateKeyExchange(); dp = dhm.ExportParameters(true); sd["openid.assoc_type"] = "HMAC-SHA256"; sd["openid.session_type"] = "DH-SHA256"; sd["openid.dh_modulus"] = Utility.UnsignedToBase64(dp.P); sd["openid.dh_gen"] = Utility.UnsignedToBase64(dp.G); sd["openid.dh_consumer_public"] = Utility.UnsignedToBase64(pubkey); break; } Tracer.Write("Opening connection to OpenID Provider."); string response = ""; string actualLocation = null; response = Utility.MakeRequest(server, "POST", sd, out actualLocation); NameValueCollection association = null; Association retassoc = null; if (response != null) { Tracer.Write("Association response received."); association = Utility.SplitResponse(response); } else { Tracer.Write("No association response received."); switch (encryption) { case KeyEncryption.DHSHA256: Tracer.Write("Falling back to DHSHA1"); encryption = KeyEncryption.DHSHA1; retassoc = CreateAssociation(server, associationManager, version, encryption); if (retassoc != null) { return retassoc; } break; case KeyEncryption.DHSHA1: Tracer.Write("Falling back to No-encryption"); encryption = KeyEncryption.None; retassoc = CreateAssociation(server, associationManager, version, encryption); if (retassoc != null) { return retassoc; } break; } return null; } if (association["error"] != null) { Tracer.Write("Association response contains error. - " + association["error"]); return null; } if (encryption == KeyEncryption.DHSHA1 || encryption == KeyEncryption.DHSHA256) { Tracer.Write("Expecting DHSHA1 or DHSHA256."); StringBuilder vals = new StringBuilder(); foreach (string key in association.Keys) { vals.AppendLine(key + ": " + association[key]); } if (association["enc_mac_key"] == null) { Tracer.Write("No encoded MAC key returned! Received " + vals.ToString()); } if (association["enc_mac_key"] != null) { Tracer.Write("Encrypted association key is present."); byte[] serverpublickey = Convert.FromBase64String(association["dh_server_public"]); byte[] mackey = Convert.FromBase64String(association["enc_mac_key"]); byte[] dhShared = dhm.DecryptKeyExchange(serverpublickey); byte[] shaShared = new byte[0]; if (encryption == KeyEncryption.DHSHA1) { Tracer.Write("Decoding DHSHA1 Association."); SHA1 sha1 = new SHA1CryptoServiceProvider(); shaShared = sha1.ComputeHash(Utility.EnsurePositive(dhShared)); } else if (encryption == KeyEncryption.DHSHA256) { Tracer.Write("Decoding DHSHA256 Association."); SHA256 sha256 = new SHA256Managed(); shaShared = sha256.ComputeHash(Utility.EnsurePositive(dhShared)); } byte[] secret = new byte[mackey.Length]; for (int i = 0; i < mackey.Length; i++) { secret[i] = (byte)(mackey[i] ^ shaShared[i]); } association["mac_key"] = Convert.ToBase64String(secret); } else { Tracer.Write("Error: Received plaintext association when expecting encrypted."); return null; } } Tracer.Write("Building association"); retassoc = new Association(); retassoc.AssociationType = association["assoc_type"]; retassoc.Expiration = DateTime.UtcNow.AddSeconds(Convert.ToDouble(association["expires_in"], CultureInfo.InvariantCulture)); retassoc.Handle = association["assoc_handle"]; retassoc.ProtocolVersion = version; retassoc.Server = server.AbsoluteUri; retassoc.SessionType = association["session_type"]; retassoc.Secret = Convert.FromBase64String(association["mac_key"]); return retassoc; }
/// <summary> /// Negotiate a new association with the OpenID Provider and add it to persistence. /// </summary> /// <param name="server">OpenID Provider URL.</param> /// <param name="associationManager">The IAssociationPersistence object to use for persistence.</param> /// <param name="version">The OpenID Version supported by the OpenID Provider discovery process.</param> /// <returns>True if the association was created successfully, false if not.</returns> internal static bool BuildAssociation(Uri server, IAssociationPersistence associationManager, ProtocolVersion version) { if (server == null) { throw new ArgumentNullException("server"); } if (associationManager == null) { throw new ArgumentNullException("associationManager"); } if (version == ProtocolVersion.Invalid) { throw new ArgumentException("Argument 'version' must not be set to 'ProtocolVersion.Invalid'"); } // Look for pre-existing valid association Tracer.Write("Looking up OpenID Provider in Associations table"); Association assoc = associationManager.FindByServer(server.AbsoluteUri); if (assoc != null) { if (assoc.Expiration > DateTime.UtcNow) { Tracer.Write("Valid association found."); return true; } } // No valid pre-existing association. Create a new association. Tracer.Write("No valid association found."); Association association = Utility.CreateAssociation(server, associationManager, version, KeyEncryption.DHSHA256); if (association != null) { associationManager.Add(association); Tracer.Write("Successfully added association to table."); return true; } return false; }