/// <summary> /// Gets an association between this Relying Party and a given Provider /// if it already exists in the association store. /// </summary> /// <param name="provider">The provider to create an association with.</param> /// <returns>The association if one exists and has useful life remaining. Otherwise <c>null</c>.</returns> internal Association GetExistingAssociation(ProviderEndpointDescription provider) { ErrorUtilities.VerifyArgumentNotNull(provider, "provider"); // If the RP has no application store for associations, there's no point in creating one. if (this.associationStore == null) { return(null); } Association association = this.associationStore.GetAssociation(provider.Endpoint, this.SecuritySettings); // If the returned association does not fulfill security requirements, ignore it. if (association != null && !this.SecuritySettings.IsAssociationInPermittedRange(association)) { association = null; } if (association != null && !association.HasUsefulLifeRemaining) { association = null; } return(association); }
private AuthenticationRequest CreateAuthenticationRequest(Identifier claimedIdentifier, Identifier providerLocalIdentifier) { ProviderEndpointDescription providerEndpoint = new ProviderEndpointDescription(OPUri, this.protocol.Version); IdentifierDiscoveryResult endpoint = IdentifierDiscoveryResult.CreateForClaimedIdentifier(claimedIdentifier, providerLocalIdentifier, providerEndpoint, 10, 5); OpenIdRelyingParty rp = this.CreateRelyingParty(); return(AuthenticationRequest.CreateForTest(endpoint, this.realm, this.returnTo, rp)); }
/// <summary> /// Runs a parameterized association flow test using all supported OpenID versions. /// </summary> /// <param name="opEndpoint">The OP endpoint to simulate using.</param> private void ParameterizedAssociationTest(Uri opEndpoint) { foreach (Protocol protocol in Protocol.AllPracticalVersions) { var endpoint = new ProviderEndpointDescription(opEndpoint, protocol.Version); var associationType = protocol.Version.Major < 2 ? protocol.Args.SignatureAlgorithm.HMAC_SHA1 : protocol.Args.SignatureAlgorithm.HMAC_SHA256; this.ParameterizedAssociationTest(endpoint, associationType); } }
/// <summary> /// Initializes a new instance of the <see cref="ServiceEndpoint"/> class. /// </summary> /// <param name="providerEndpoint">The provider endpoint.</param> /// <param name="claimedIdentifier">The Claimed Identifier.</param> /// <param name="userSuppliedIdentifier">The User-supplied Identifier.</param> /// <param name="providerLocalIdentifier">The Provider Local Identifier.</param> /// <param name="servicePriority">The service priority.</param> /// <param name="uriPriority">The URI priority.</param> private ServiceEndpoint(ProviderEndpointDescription providerEndpoint, Identifier claimedIdentifier, Identifier userSuppliedIdentifier, Identifier providerLocalIdentifier, int?servicePriority, int?uriPriority) { ErrorUtilities.VerifyArgumentNotNull(claimedIdentifier, "claimedIdentifier"); ErrorUtilities.VerifyArgumentNotNull(providerEndpoint, "providerEndpoint"); this.ProviderDescription = providerEndpoint; this.ClaimedIdentifier = claimedIdentifier; this.UserSuppliedIdentifier = userSuppliedIdentifier; this.ProviderLocalIdentifier = providerLocalIdentifier ?? claimedIdentifier; this.servicePriority = servicePriority; this.uriPriority = uriPriority; }
protected Identifier GetMockDualIdentifier() { Protocol protocol = Protocol.Default; var opDesc = new ProviderEndpointDescription(OPUri, protocol.Version); var dualResults = new IdentifierDiscoveryResult[] { IdentifierDiscoveryResult.CreateForClaimedIdentifier(VanityUri.AbsoluteUri, OPLocalIdentifiers[0], opDesc, 10, 10), IdentifierDiscoveryResult.CreateForProviderIdentifier(protocol.ClaimedIdentifierForOPIdentifier, opDesc, 20, 20), }; this.RegisterMockXrdsResponse(VanityUri, dualResults); return(VanityUri); }
public async Task AssociateRenegotiateBitLength() { Protocol protocol = Protocol.V20; // The strategy is to make a simple request of the RP to establish an association, // and to more carefully observe the Provider-side of things to make sure that both // the OP and RP are behaving as expected. int providerAttemptCount = 0; HandleProvider( async(op, request) => { op.SecuritySettings.MaximumHashBitLength = 160; // Force OP to reject HMAC-SHA256 switch (++providerAttemptCount) { case 1: // Receive initial request for an HMAC-SHA256 association. var req = (AutoResponsiveRequest)await op.GetRequestAsync(request); var associateRequest = (AssociateRequest)req.RequestMessage; Assert.That(associateRequest, Is.Not.Null); Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA256, associateRequest.AssociationType); // Ensure that the response is a suggestion that the RP try again with HMAC-SHA1 var renegotiateResponse = (AssociateUnsuccessfulResponse)await req.GetResponseMessageAsyncTestHook(CancellationToken.None); Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, renegotiateResponse.AssociationType); return(await op.PrepareResponseAsync(req)); case 2: // Receive second attempt request for an HMAC-SHA1 association. req = (AutoResponsiveRequest)await op.GetRequestAsync(request); associateRequest = (AssociateRequest)req.RequestMessage; Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, associateRequest.AssociationType); // Ensure that the response is a success response. var successResponse = (AssociateSuccessfulResponse)await req.GetResponseMessageAsyncTestHook(CancellationToken.None); Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, successResponse.AssociationType); return(await op.PrepareResponseAsync(req)); default: throw Assumes.NotReachable(); } }); var rp = this.CreateRelyingParty(); var opDescription = new ProviderEndpointDescription(OPUri, protocol.Version); Association association = await rp.AssociationManager.GetOrCreateAssociationAsync(opDescription, CancellationToken.None); Assert.IsNotNull(association, "Association failed to be created."); Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, association.GetAssociationType(protocol)); }
public void AssociateRequestDeterminedBySecuritySettings() { Protocol protocol = Protocol.V20; SecuritySettings securitySettings = new RelyingPartySecuritySettings(); securitySettings.MinimumHashBitLength = 160; securitySettings.MaximumHashBitLength = 160; ProviderEndpointDescription provider = new ProviderEndpointDescription(OPUri, protocol.Version); Assert.AreEqual(AssociateRequestRelyingParty.Create(securitySettings, provider).AssociationType, protocol.Args.SignatureAlgorithm.HMAC_SHA1); securitySettings.MinimumHashBitLength = 384; securitySettings.MaximumHashBitLength = 384; Assert.AreEqual(AssociateRequestRelyingParty.Create(securitySettings, provider).AssociationType, protocol.Args.SignatureAlgorithm.HMAC_SHA384); }
internal static IdentifierDiscoveryResult GetServiceEndpoint(int user, ProtocolVersion providerVersion, int servicePriority, bool useSsl, bool delegating) { var providerEndpoint = new ProviderEndpointDescription( useSsl ? OpenIdTestBase.OPUriSsl : OpenIdTestBase.OPUri, new string[] { Protocol.Lookup(providerVersion).ClaimedIdentifierServiceTypeURI }); var local_id = useSsl ? OPLocalIdentifiersSsl[user] : OPLocalIdentifiers[user]; var claimed_id = delegating ? (useSsl ? VanityUriSsl : VanityUri) : local_id; return(IdentifierDiscoveryResult.CreateForClaimedIdentifier( claimed_id, claimed_id, local_id, providerEndpoint, servicePriority, 10)); }
/// <summary> /// Creates a new association with a given Provider. /// </summary> /// <param name="provider">The provider to create an association with.</param> /// <returns> /// The newly created association, or null if no association can be created with /// the given Provider given the current security settings. /// </returns> /// <remarks> /// A new association is created and returned even if one already exists in the /// association store. /// Any new association is automatically added to the <see cref="associationStore"/>. /// </remarks> private Association CreateNewAssociation(ProviderEndpointDescription provider) { ErrorUtilities.VerifyArgumentNotNull(provider, "provider"); // If there is no association store, there is no point in creating an association. if (this.associationStore == null) { return(null); } var associateRequest = AssociateRequest.Create(this.securitySettings, provider); const int RenegotiateRetries = 1; return(this.CreateNewAssociation(provider, associateRequest, RenegotiateRetries)); }
public async Task GetRequest() { var httpInfo = new HttpRequestMessage(HttpMethod.Get, "http://someUri"); Assert.IsNull(await this.provider.GetRequestAsync(httpInfo), "An irrelevant request should return null."); var providerDescription = new ProviderEndpointDescription(OPUri, Protocol.Default.Version); // Test some non-empty request scenario. HandleProvider( async(op, req) => { IRequest request = await op.GetRequestAsync(req); Assert.IsInstanceOf <AutoResponsiveRequest>(request); return(await op.PrepareResponseAsync(request)); }); var rp = this.CreateRelyingParty(); await rp.Channel.RequestAsync(AssociateRequestRelyingParty.Create(rp.SecuritySettings, providerDescription), CancellationToken.None); }
public void ProblematicClaimedId() { var providerEndpoint = new ProviderEndpointDescription(OpenIdTestBase.OPUri, Protocol.Default.Version); string claimed_id = BaseMockUri + "a./b."; var se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(claimed_id, claimed_id, providerEndpoint, null, null); UriIdentifier identityUri = (UriIdentifier)se.ClaimedIdentifier; var mockId = new MockIdentifier(identityUri, this.MockResponder, new IdentifierDiscoveryResult[] { se }); var positiveAssertion = this.GetPositiveAssertion(); positiveAssertion.ClaimedIdentifier = mockId; positiveAssertion.LocalIdentifier = mockId; var rp = CreateRelyingParty(); var authResponse = new PositiveAuthenticationResponse(positiveAssertion, rp); Assert.AreEqual(AuthenticationStatus.Authenticated, authResponse.Status); Assert.AreEqual(claimed_id, authResponse.ClaimedIdentifier.ToString()); }
public async Task ProblematicClaimedId() { var providerEndpoint = new ProviderEndpointDescription(OpenIdTestBase.OPUri, Protocol.Default.Version); string claimed_id = BaseMockUri + "a./b."; var se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(claimed_id, claimed_id, providerEndpoint, null, null); var identityUri = (UriIdentifier)se.ClaimedIdentifier; this.RegisterMockXrdsResponse(se); var rp = this.CreateRelyingParty(); var positiveAssertion = this.GetPositiveAssertion(); positiveAssertion.ClaimedIdentifier = claimed_id; positiveAssertion.LocalIdentifier = claimed_id; var authResponse = await PositiveAuthenticationResponse.CreateAsync(positiveAssertion, rp, CancellationToken.None); Assert.AreEqual(AuthenticationStatus.Authenticated, authResponse.Status); Assert.AreEqual(claimed_id, authResponse.ClaimedIdentifier.ToString()); }
public void AssociateRenegotiateBitLength() { Protocol protocol = Protocol.V20; // The strategy is to make a simple request of the RP to establish an association, // and to more carefully observe the Provider-side of things to make sure that both // the OP and RP are behaving as expected. OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { var opDescription = new ProviderEndpointDescription(OPUri, protocol.Version); Association association = rp.AssociationManager.GetOrCreateAssociation(opDescription); Assert.IsNotNull(association, "Association failed to be created."); Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, association.GetAssociationType(protocol)); }, op => { op.SecuritySettings.MaximumHashBitLength = 160; // Force OP to reject HMAC-SHA256 // Receive initial request for an HMAC-SHA256 association. AutoResponsiveRequest req = (AutoResponsiveRequest)op.GetRequest(); AutoResponsiveRequest_Accessor reqAccessor = AutoResponsiveRequest_Accessor.AttachShadow(req); AssociateRequest associateRequest = (AssociateRequest)reqAccessor.RequestMessage; Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA256, associateRequest.AssociationType); // Ensure that the response is a suggestion that the RP try again with HMAC-SHA1 AssociateUnsuccessfulResponse renegotiateResponse = (AssociateUnsuccessfulResponse)reqAccessor.ResponseMessage; Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, renegotiateResponse.AssociationType); op.SendResponse(req); // Receive second attempt request for an HMAC-SHA1 association. req = (AutoResponsiveRequest)op.GetRequest(); reqAccessor = AutoResponsiveRequest_Accessor.AttachShadow(req); associateRequest = (AssociateRequest)reqAccessor.RequestMessage; Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, associateRequest.AssociationType); // Ensure that the response is a success response. AssociateSuccessfulResponse successResponse = (AssociateSuccessfulResponse)reqAccessor.ResponseMessage; Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, successResponse.AssociationType); op.SendResponse(req); }); coordinator.Run(); }
public void GetRequest() { var httpInfo = new HttpRequestInfo("GET", new Uri("http://someUri")); Assert.IsNull(this.provider.GetRequest(httpInfo), "An irrelevant request should return null."); var providerDescription = new ProviderEndpointDescription(OPUri, Protocol.Default.Version); // Test some non-empty request scenario. OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { rp.Channel.Request(AssociateRequestRelyingParty.Create(rp.SecuritySettings, providerDescription)); }, op => { IRequest request = op.GetRequest(); Assert.IsInstanceOf <AutoResponsiveRequest>(request); op.Respond(request); }); coordinator.Run(); }
/// <summary> /// Gets an association between this Relying Party and a given Provider /// if it already exists in the association store. /// </summary> /// <param name="provider">The provider to create an association with.</param> /// <returns>The association if one exists and has useful life remaining. Otherwise <c>null</c>.</returns> internal Association GetExistingAssociation(ProviderEndpointDescription provider) { ErrorUtilities.VerifyArgumentNotNull(provider, "provider"); // If the RP has no application store for associations, there's no point in creating one. if (this.associationStore == null) { return null; } Association association = this.associationStore.GetAssociation(provider.Endpoint, this.SecuritySettings); // If the returned association does not fulfill security requirements, ignore it. if (association != null && !this.SecuritySettings.IsAssociationInPermittedRange(association)) { association = null; } if (association != null && !association.HasUsefulLifeRemaining) { association = null; } return association; }
/// <summary> /// Creates an association request message that is appropriate for a given Provider. /// </summary> /// <param name="securityRequirements">The set of requirements the selected association type must comply to.</param> /// <param name="provider">The provider to create an association with.</param> /// <returns> /// The message to send to the Provider to request an association. /// Null if no association could be created that meet the security requirements /// and the provider OpenID version. /// </returns> internal static AssociateRequest Create(SecuritySettings securityRequirements, ProviderEndpointDescription provider) { ErrorUtilities.VerifyArgumentNotNull(securityRequirements, "securityRequirements"); ErrorUtilities.VerifyArgumentNotNull(provider, "provider"); // Apply our knowledge of the endpoint's transport, OpenID version, and // security requirements to decide the best association. bool unencryptedAllowed = provider.Endpoint.IsTransportSecure(); bool useDiffieHellman = !unencryptedAllowed; string associationType, sessionType; if (!HmacShaAssociation.TryFindBestAssociation(Protocol.Lookup(provider.ProtocolVersion), true, securityRequirements, useDiffieHellman, out associationType, out sessionType)) { // There are no associations that meet all requirements. Logger.OpenId.Warn("Security requirements and protocol combination knock out all possible association types. Dumb mode forced."); return null; } return Create(securityRequirements, provider, associationType, sessionType); }
/// <summary> /// Creates an association request message that is appropriate for a given Provider. /// </summary> /// <param name="securityRequirements">The set of requirements the selected association type must comply to.</param> /// <param name="provider">The provider to create an association with.</param> /// <param name="associationType">Type of the association.</param> /// <param name="sessionType">Type of the session.</param> /// <returns> /// The message to send to the Provider to request an association. /// Null if no association could be created that meet the security requirements /// and the provider OpenID version. /// </returns> internal static AssociateRequest Create(SecuritySettings securityRequirements, ProviderEndpointDescription provider, string associationType, string sessionType) { ErrorUtilities.VerifyArgumentNotNull(securityRequirements, "securityRequirements"); ErrorUtilities.VerifyArgumentNotNull(provider, "provider"); ErrorUtilities.VerifyNonZeroLength(associationType, "associationType"); ErrorUtilities.VerifyArgumentNotNull(sessionType, "sessionType"); bool unencryptedAllowed = provider.Endpoint.IsTransportSecure(); if (unencryptedAllowed) { var associateRequest = new AssociateUnencryptedRequest(provider.ProtocolVersion, provider.Endpoint); associateRequest.AssociationType = associationType; return associateRequest; } else { var associateRequest = new AssociateDiffieHellmanRequest(provider.ProtocolVersion, provider.Endpoint); associateRequest.AssociationType = associationType; associateRequest.SessionType = sessionType; associateRequest.InitializeRequest(); return associateRequest; } }
/// <summary> /// Runs a parameterized association flow test. /// </summary> /// <param name="opDescription"> /// The description of the Provider that the relying party uses to formulate the request. /// The specific host is not used, but the scheme is significant. /// </param> /// <param name="expectedAssociationType"> /// The value of the openid.assoc_type parameter expected, /// or null if a failure is anticipated. /// </param> private void ParameterizedAssociationTest( ProviderEndpointDescription opDescription, string expectedAssociationType) { Protocol protocol = Protocol.Lookup(Protocol.Lookup(opDescription.Version).ProtocolVersion); bool expectSuccess = expectedAssociationType != null; bool expectDiffieHellman = !opDescription.Uri.IsTransportSecure(); Association rpAssociation = null, opAssociation; AssociateSuccessfulResponse associateSuccessfulResponse = null; AssociateUnsuccessfulResponse associateUnsuccessfulResponse = null; OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { rp.SecuritySettings = this.RelyingPartySecuritySettings; rpAssociation = rp.AssociationManager.GetOrCreateAssociation(opDescription); }, op => { op.SecuritySettings = this.ProviderSecuritySettings; IRequest req = op.GetRequest(); Assert.IsNotNull(req, "Expected incoming request but did not receive it."); Assert.IsTrue(req.IsResponseReady); op.Respond(req); }); coordinator.IncomingMessageFilter = message => { Assert.AreSame(opDescription.Version, message.Version, "The message was recognized as version {0} but was expected to be {1}.", message.Version, Protocol.Lookup(opDescription.Version).ProtocolVersion); var associateSuccess = message as AssociateSuccessfulResponse; var associateFailed = message as AssociateUnsuccessfulResponse; if (associateSuccess != null) { associateSuccessfulResponse = associateSuccess; } if (associateFailed != null) { associateUnsuccessfulResponse = associateFailed; } }; coordinator.OutgoingMessageFilter = message => { Assert.AreEqual(opDescription.Version, message.Version, "The message was for version {0} but was expected to be for {1}.", message.Version, opDescription.Version); }; coordinator.Run(); if (expectSuccess) { Assert.IsNotNull(rpAssociation); Association actual = coordinator.RelyingParty.AssociationManager.AssociationStoreTestHook.GetAssociation(opDescription.Uri, rpAssociation.Handle); Assert.AreEqual(rpAssociation, actual); opAssociation = coordinator.Provider.AssociationStore.Deserialize(new TestSignedDirectedMessage(), false, rpAssociation.Handle); Assert.IsNotNull(opAssociation, "The Provider could not decode the association handle."); Assert.AreEqual(opAssociation.Handle, rpAssociation.Handle); Assert.AreEqual(expectedAssociationType, rpAssociation.GetAssociationType(protocol)); Assert.AreEqual(expectedAssociationType, opAssociation.GetAssociationType(protocol)); Assert.IsTrue(Math.Abs(opAssociation.SecondsTillExpiration - rpAssociation.SecondsTillExpiration) < 60); Assert.IsTrue(MessagingUtilities.AreEquivalent(opAssociation.SecretKey, rpAssociation.SecretKey)); if (expectDiffieHellman) { Assert.IsInstanceOf <AssociateDiffieHellmanResponse>(associateSuccessfulResponse); var diffieHellmanResponse = (AssociateDiffieHellmanResponse)associateSuccessfulResponse; Assert.IsFalse(MessagingUtilities.AreEquivalent(diffieHellmanResponse.EncodedMacKey, rpAssociation.SecretKey), "Key should have been encrypted."); } else { Assert.IsInstanceOf <AssociateUnencryptedResponse>(associateSuccessfulResponse); var unencryptedResponse = (AssociateUnencryptedResponse)associateSuccessfulResponse; } } else { Assert.IsNull(coordinator.RelyingParty.AssociationManager.AssociationStoreTestHook.GetAssociation(opDescription.Uri, new RelyingPartySecuritySettings())); } }
/// <summary> /// Creates a new association with a given Provider. /// </summary> /// <param name="provider">The provider to create an association with.</param> /// <param name="associateRequest">The associate request. May be <c>null</c>, which will always result in a <c>null</c> return value..</param> /// <param name="retriesRemaining">The number of times to try the associate request again if the Provider suggests it.</param> /// <returns> /// The newly created association, or null if no association can be created with /// the given Provider given the current security settings. /// </returns> private Association CreateNewAssociation(ProviderEndpointDescription provider, AssociateRequest associateRequest, int retriesRemaining) { ErrorUtilities.VerifyArgumentNotNull(provider, "provider"); if (associateRequest == null || retriesRemaining < 0) { // this can happen if security requirements and protocol conflict // to where there are no association types to choose from. return null; } try { var associateResponse = this.channel.Request(associateRequest); var associateSuccessfulResponse = associateResponse as AssociateSuccessfulResponse; var associateUnsuccessfulResponse = associateResponse as AssociateUnsuccessfulResponse; if (associateSuccessfulResponse != null) { Association association = associateSuccessfulResponse.CreateAssociation(associateRequest, null); this.associationStore.StoreAssociation(provider.Endpoint, association); return association; } else if (associateUnsuccessfulResponse != null) { if (string.IsNullOrEmpty(associateUnsuccessfulResponse.AssociationType)) { Logger.OpenId.Debug("Provider rejected an association request and gave no suggestion as to an alternative association type. Giving up."); return null; } if (!this.securitySettings.IsAssociationInPermittedRange(Protocol.Lookup(provider.ProtocolVersion), associateUnsuccessfulResponse.AssociationType)) { Logger.OpenId.DebugFormat("Provider rejected an association request and suggested '{0}' as an association to try, which this Relying Party does not support. Giving up.", associateUnsuccessfulResponse.AssociationType); return null; } if (retriesRemaining <= 0) { Logger.OpenId.Debug("Unable to agree on an association type with the Provider in the allowed number of retries. Giving up."); return null; } // Make sure the Provider isn't suggesting an incompatible pair of association/session types. Protocol protocol = Protocol.Lookup(provider.ProtocolVersion); ErrorUtilities.VerifyProtocol( HmacShaAssociation.IsDHSessionCompatible(protocol, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType), OpenIdStrings.IncompatibleAssociationAndSessionTypes, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType); associateRequest = AssociateRequest.Create(this.securitySettings, provider, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType); return this.CreateNewAssociation(provider, associateRequest, retriesRemaining - 1); } else { throw new ProtocolException(MessagingStrings.UnexpectedMessageReceivedOfMany); } } catch (ProtocolException ex) { // If the association failed because the remote server can't handle Expect: 100 Continue headers, // then our web request handler should have already accomodated for future calls. Go ahead and // immediately make one of those future calls now to try to get the association to succeed. if (StandardWebRequestHandler.IsExceptionFrom417ExpectationFailed(ex)) { return this.CreateNewAssociation(provider, associateRequest, retriesRemaining - 1); } // Since having associations with OPs is not totally critical, we'll log and eat // the exception so that auth may continue in dumb mode. Logger.OpenId.ErrorFormat("An error occurred while trying to create an association with {0}. {1}", provider.Endpoint, ex); return null; } }
/// <summary> /// Creates an association request message that is appropriate for a given Provider. /// </summary> /// <param name="securityRequirements">The set of requirements the selected association type must comply to.</param> /// <param name="provider">The provider to create an association with.</param> /// <param name="associationType">Type of the association.</param> /// <param name="sessionType">Type of the session.</param> /// <returns> /// The message to send to the Provider to request an association. /// Null if no association could be created that meet the security requirements /// and the provider OpenID version. /// </returns> internal static AssociateRequest Create(SecuritySettings securityRequirements, ProviderEndpointDescription provider, string associationType, string sessionType) { ErrorUtilities.VerifyArgumentNotNull(securityRequirements, "securityRequirements"); ErrorUtilities.VerifyArgumentNotNull(provider, "provider"); ErrorUtilities.VerifyNonZeroLength(associationType, "associationType"); ErrorUtilities.VerifyArgumentNotNull(sessionType, "sessionType"); bool unencryptedAllowed = provider.Endpoint.IsTransportSecure(); if (unencryptedAllowed) { var associateRequest = new AssociateUnencryptedRequest(provider.ProtocolVersion, provider.Endpoint); associateRequest.AssociationType = associationType; return(associateRequest); } else { var associateRequest = new AssociateDiffieHellmanRequest(provider.ProtocolVersion, provider.Endpoint); associateRequest.AssociationType = associationType; associateRequest.SessionType = sessionType; associateRequest.InitializeRequest(); return(associateRequest); } }
/// <summary> /// Creates a new association with a given Provider. /// </summary> /// <param name="provider">The provider to create an association with.</param> /// <param name="associateRequest">The associate request. May be <c>null</c>, which will always result in a <c>null</c> return value..</param> /// <param name="retriesRemaining">The number of times to try the associate request again if the Provider suggests it.</param> /// <returns> /// The newly created association, or null if no association can be created with /// the given Provider given the current security settings. /// </returns> private Association CreateNewAssociation(ProviderEndpointDescription provider, AssociateRequest associateRequest, int retriesRemaining) { ErrorUtilities.VerifyArgumentNotNull(provider, "provider"); if (associateRequest == null || retriesRemaining < 0) { // this can happen if security requirements and protocol conflict // to where there are no association types to choose from. return(null); } try { var associateResponse = this.channel.Request(associateRequest); var associateSuccessfulResponse = associateResponse as AssociateSuccessfulResponse; var associateUnsuccessfulResponse = associateResponse as AssociateUnsuccessfulResponse; if (associateSuccessfulResponse != null) { Association association = associateSuccessfulResponse.CreateAssociation(associateRequest, null); this.associationStore.StoreAssociation(provider.Endpoint, association); return(association); } else if (associateUnsuccessfulResponse != null) { if (string.IsNullOrEmpty(associateUnsuccessfulResponse.AssociationType)) { Logger.Debug("Provider rejected an association request and gave no suggestion as to an alternative association type. Giving up."); return(null); } if (!this.securitySettings.IsAssociationInPermittedRange(Protocol.Lookup(provider.ProtocolVersion), associateUnsuccessfulResponse.AssociationType)) { Logger.DebugFormat("Provider rejected an association request and suggested '{0}' as an association to try, which this Relying Party does not support. Giving up.", associateUnsuccessfulResponse.AssociationType); return(null); } if (retriesRemaining <= 0) { Logger.Debug("Unable to agree on an association type with the Provider in the allowed number of retries. Giving up."); return(null); } // Make sure the Provider isn't suggesting an incompatible pair of association/session types. Protocol protocol = Protocol.Lookup(provider.ProtocolVersion); ErrorUtilities.VerifyProtocol( HmacShaAssociation.IsDHSessionCompatible(protocol, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType), OpenIdStrings.IncompatibleAssociationAndSessionTypes, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType); associateRequest = AssociateRequest.Create(this.securitySettings, provider, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType); return(this.CreateNewAssociation(provider, associateRequest, retriesRemaining - 1)); } else { throw new ProtocolException(MessagingStrings.UnexpectedMessageReceivedOfMany); } } catch (ProtocolException ex) { // Since having associations with OPs is not totally critical, we'll log and eat // the exception so that auth may continue in dumb mode. Logger.ErrorFormat("An error occurred while trying to create an association with {0}. {1}", provider.Endpoint, ex); return(null); } }
/// <summary> /// Creates a <see cref="ServiceEndpoint"/> instance to represent some OP Identifier. /// </summary> /// <param name="providerIdentifier">The provider identifier.</param> /// <param name="providerEndpoint">The provider endpoint.</param> /// <param name="servicePriority">The service priority.</param> /// <param name="uriPriority">The URI priority.</param> /// <returns>The created <see cref="ServiceEndpoint"/> instance</returns> internal static ServiceEndpoint CreateForProviderIdentifier(Identifier providerIdentifier, ProviderEndpointDescription providerEndpoint, int?servicePriority, int?uriPriority) { ErrorUtilities.VerifyArgumentNotNull(providerEndpoint, "providerEndpoint"); Protocol protocol = Protocol.Detect(providerEndpoint.Capabilities); return(new ServiceEndpoint( providerEndpoint, protocol.ClaimedIdentifierForOPIdentifier, providerIdentifier, protocol.ClaimedIdentifierForOPIdentifier, servicePriority, uriPriority)); }
/// <summary> /// Gets an existing association with the specified Provider, or attempts to create /// a new association of one does not already exist. /// </summary> /// <param name="provider">The provider to get an association for.</param> /// <returns>The existing or new association; <c>null</c> if none existed and one could not be created.</returns> internal Association GetOrCreateAssociation(ProviderEndpointDescription provider) { return(this.GetExistingAssociation(provider) ?? this.CreateNewAssociation(provider)); }
/// <summary> /// Creates a <see cref="ServiceEndpoint"/> instance to represent some Claimed Identifier. /// </summary> /// <param name="claimedIdentifier">The claimed identifier.</param> /// <param name="providerLocalIdentifier">The provider local identifier.</param> /// <param name="providerEndpoint">The provider endpoint.</param> /// <param name="servicePriority">The service priority.</param> /// <param name="uriPriority">The URI priority.</param> /// <returns>The created <see cref="ServiceEndpoint"/> instance</returns> internal static ServiceEndpoint CreateForClaimedIdentifier(Identifier claimedIdentifier, Identifier providerLocalIdentifier, ProviderEndpointDescription providerEndpoint, int?servicePriority, int?uriPriority) { return(CreateForClaimedIdentifier(claimedIdentifier, null, providerLocalIdentifier, providerEndpoint, servicePriority, uriPriority)); }
/// <summary> /// Gets an existing association with the specified Provider, or attempts to create /// a new association of one does not already exist. /// </summary> /// <param name="provider">The provider to get an association for.</param> /// <returns>The existing or new association; <c>null</c> if none existed and one could not be created.</returns> internal Association GetOrCreateAssociation(ProviderEndpointDescription provider) { return this.GetExistingAssociation(provider) ?? this.CreateNewAssociation(provider); }
/// <summary> /// Creates an association request message that is appropriate for a given Provider. /// </summary> /// <param name="securityRequirements">The set of requirements the selected association type must comply to.</param> /// <param name="provider">The provider to create an association with.</param> /// <returns> /// The message to send to the Provider to request an association. /// Null if no association could be created that meet the security requirements /// and the provider OpenID version. /// </returns> internal static AssociateRequest Create(SecuritySettings securityRequirements, ProviderEndpointDescription provider) { ErrorUtilities.VerifyArgumentNotNull(securityRequirements, "securityRequirements"); ErrorUtilities.VerifyArgumentNotNull(provider, "provider"); // Apply our knowledge of the endpoint's transport, OpenID version, and // security requirements to decide the best association. bool unencryptedAllowed = provider.Endpoint.IsTransportSecure(); bool useDiffieHellman = !unencryptedAllowed; string associationType, sessionType; if (!HmacShaAssociation.TryFindBestAssociation(Protocol.Lookup(provider.ProtocolVersion), true, securityRequirements, useDiffieHellman, out associationType, out sessionType)) { // There are no associations that meet all requirements. Logger.Warn("Security requirements and protocol combination knock out all possible association types. Dumb mode forced."); return(null); } return(Create(securityRequirements, provider, associationType, sessionType)); }
/// <summary> /// Creates a new association with a given Provider. /// </summary> /// <param name="provider">The provider to create an association with.</param> /// <returns> /// The newly created association, or null if no association can be created with /// the given Provider given the current security settings. /// </returns> /// <remarks> /// A new association is created and returned even if one already exists in the /// association store. /// Any new association is automatically added to the <see cref="associationStore"/>. /// </remarks> private Association CreateNewAssociation(ProviderEndpointDescription provider) { ErrorUtilities.VerifyArgumentNotNull(provider, "provider"); // If there is no association store, there is no point in creating an association. if (this.associationStore == null) { return null; } var associateRequest = AssociateRequest.Create(this.securitySettings, provider); const int RenegotiateRetries = 1; return this.CreateNewAssociation(provider, associateRequest, RenegotiateRetries); }
public void NonNullCapabilities() { var epd = new ProviderEndpointDescription(OPUri, Protocol.Default.Version); Assert.IsNotNull(epd.Capabilities); }
/// <summary> /// Runs a parameterized association flow test. /// </summary> /// <param name="opDescription"> /// The description of the Provider that the relying party uses to formulate the request. /// The specific host is not used, but the scheme is significant. /// </param> /// <param name="expectedAssociationType"> /// The value of the openid.assoc_type parameter expected, /// or null if a failure is anticipated. /// </param> private async Task ParameterizedAssociationTestAsync( ProviderEndpointDescription opDescription, string expectedAssociationType) { Protocol protocol = Protocol.Lookup(Protocol.Lookup(opDescription.Version).ProtocolVersion); bool expectSuccess = expectedAssociationType != null; bool expectDiffieHellman = !opDescription.Uri.IsTransportSecure(); Association rpAssociation = null, opAssociation; AssociateSuccessfulResponse associateSuccessfulResponse = null; AssociateUnsuccessfulResponse associateUnsuccessfulResponse = null; var relyingParty = new OpenIdRelyingParty(new MemoryCryptoKeyAndNonceStore(), this.HostFactories); var provider = new OpenIdProvider(new MemoryCryptoKeyAndNonceStore(), this.HostFactories) { SecuritySettings = this.ProviderSecuritySettings }; Handle(opDescription.Uri).By( async(request, ct) => { IRequest req = await provider.GetRequestAsync(request, ct); Assert.IsNotNull(req, "Expected incoming request but did not receive it."); Assert.IsTrue(req.IsResponseReady); return(await provider.PrepareResponseAsync(req, ct)); }); relyingParty.Channel.IncomingMessageFilter = message => { Assert.AreSame(opDescription.Version, message.Version, "The message was recognized as version {0} but was expected to be {1}.", message.Version, Protocol.Lookup(opDescription.Version).ProtocolVersion); var associateSuccess = message as AssociateSuccessfulResponse; var associateFailed = message as AssociateUnsuccessfulResponse; if (associateSuccess != null) { associateSuccessfulResponse = associateSuccess; } if (associateFailed != null) { associateUnsuccessfulResponse = associateFailed; } }; relyingParty.Channel.OutgoingMessageFilter = message => { Assert.AreEqual(opDescription.Version, message.Version, "The message was for version {0} but was expected to be for {1}.", message.Version, opDescription.Version); }; relyingParty.SecuritySettings = this.RelyingPartySecuritySettings; rpAssociation = await relyingParty.AssociationManager.GetOrCreateAssociationAsync(opDescription, CancellationToken.None); if (expectSuccess) { Assert.IsNotNull(rpAssociation); Association actual = relyingParty.AssociationManager.AssociationStoreTestHook.GetAssociation(opDescription.Uri, rpAssociation.Handle); Assert.AreEqual(rpAssociation, actual); opAssociation = provider.AssociationStore.Deserialize(new TestSignedDirectedMessage(), false, rpAssociation.Handle); Assert.IsNotNull(opAssociation, "The Provider could not decode the association handle."); Assert.AreEqual(opAssociation.Handle, rpAssociation.Handle); Assert.AreEqual(expectedAssociationType, rpAssociation.GetAssociationType(protocol)); Assert.AreEqual(expectedAssociationType, opAssociation.GetAssociationType(protocol)); Assert.IsTrue(Math.Abs(opAssociation.SecondsTillExpiration - rpAssociation.SecondsTillExpiration) < 60); Assert.IsTrue(MessagingUtilities.AreEquivalent(opAssociation.SecretKey, rpAssociation.SecretKey)); if (expectDiffieHellman) { Assert.IsInstanceOf <AssociateDiffieHellmanResponse>(associateSuccessfulResponse); var diffieHellmanResponse = (AssociateDiffieHellmanResponse)associateSuccessfulResponse; Assert.IsFalse(MessagingUtilities.AreEquivalent(diffieHellmanResponse.EncodedMacKey, rpAssociation.SecretKey), "Key should have been encrypted."); } else { Assert.IsInstanceOf <AssociateUnencryptedResponse>(associateSuccessfulResponse); var unencryptedResponse = (AssociateUnencryptedResponse)associateSuccessfulResponse; } } else { Assert.IsNull(relyingParty.AssociationManager.AssociationStoreTestHook.GetAssociation(opDescription.Uri, new RelyingPartySecuritySettings())); } }
/// <summary> /// Creates a <see cref="ServiceEndpoint"/> instance to represent some Claimed Identifier. /// </summary> /// <param name="claimedIdentifier">The claimed identifier.</param> /// <param name="userSuppliedIdentifier">The user supplied identifier.</param> /// <param name="providerLocalIdentifier">The provider local identifier.</param> /// <param name="providerEndpoint">The provider endpoint.</param> /// <param name="servicePriority">The service priority.</param> /// <param name="uriPriority">The URI priority.</param> /// <returns>The created <see cref="ServiceEndpoint"/> instance</returns> internal static ServiceEndpoint CreateForClaimedIdentifier(Identifier claimedIdentifier, Identifier userSuppliedIdentifier, Identifier providerLocalIdentifier, ProviderEndpointDescription providerEndpoint, int?servicePriority, int?uriPriority) { return(new ServiceEndpoint(providerEndpoint, claimedIdentifier, userSuppliedIdentifier, providerLocalIdentifier, servicePriority, uriPriority)); }