/// <summary> /// Creates a new association with a given Provider. /// </summary> /// <param name="provider">The provider to create an association with.</param> /// <param name="cancellationToken">The cancellation token.</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 async Task <Association> CreateNewAssociationAsync(IProviderEndpoint provider, CancellationToken cancellationToken) { Requires.NotNull(provider, "provider"); // If there is no association store, there is no point in creating an association. if (this.associationStore == null) { return(null); } try { var associateRequest = AssociateRequestRelyingParty.Create(this.securitySettings, provider); const int RenegotiateRetries = 1; return(await this.CreateNewAssociationAsync(provider, associateRequest, RenegotiateRetries, cancellationToken)); } catch (VerificationException ex) { // See Trac ticket #163. In partial trust host environments, the // Diffie-Hellman implementation we're using for HTTP OP endpoints // sometimes causes the CLR to throw: // "VerificationException: Operation could destabilize the runtime." // Just give up and use dumb mode in this case. Logger.OpenId.ErrorFormat("VerificationException occurred while trying to create an association with {0}. {1}", provider.Uri, ex); return(null); } }
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); }
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); }
private HttpRequestInfo CreateAssociateRequest(Uri opEndpoint) { var rp = CreateRelyingParty(true); AssociateRequest associateMessage = AssociateRequestRelyingParty.Create(rp.SecuritySettings, new ProviderEndpointDescription(opEndpoint, Protocol.Default.Version)); Channel rpChannel = rp.Channel; MemoryStream ms = new MemoryStream(); StreamWriter mswriter = new StreamWriter(ms); mswriter.Write(MessagingUtilities.CreateQueryString(rpChannel.MessageDescriptions.GetAccessor(associateMessage))); mswriter.Flush(); ms.Position = 0; var headers = new WebHeaderCollection(); headers.Add(HttpRequestHeader.ContentType, Channel.HttpFormUrlEncoded); var httpRequest = new HttpRequestInfo("POST", opEndpoint, headers, ms); return(httpRequest); }
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> /// 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> /// <param name="cancellationToken">The cancellation token.</param> /// <returns> /// The newly created association, or null if no association can be created with /// the given Provider given the current security settings. /// </returns> /// <exception cref="ProtocolException">Create if an error occurs while creating the new association.</exception> private async Task <Association> CreateNewAssociationAsync(IProviderEndpoint provider, AssociateRequest associateRequest, int retriesRemaining, CancellationToken cancellationToken) { Requires.NotNull(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); } Exception exception = null; try { var associateResponse = await this.channel.RequestAsync(associateRequest, cancellationToken); var associateSuccessfulResponse = associateResponse as IAssociateSuccessfulResponseRelyingParty; var associateUnsuccessfulResponse = associateResponse as AssociateUnsuccessfulResponse; if (associateSuccessfulResponse != null) { Association association = associateSuccessfulResponse.CreateAssociationAtRelyingParty(associateRequest); this.associationStore.StoreAssociation(provider.Uri, 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.Version), 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.Version); ErrorUtilities.VerifyProtocol( HmacShaAssociation.IsDHSessionCompatible(protocol, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType), OpenIdStrings.IncompatibleAssociationAndSessionTypes, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType); associateRequest = AssociateRequestRelyingParty.Create(this.securitySettings, provider, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType); return(await this.CreateNewAssociationAsync(provider, associateRequest, retriesRemaining - 1, cancellationToken)); } else { throw new ProtocolException(MessagingStrings.UnexpectedMessageReceivedOfMany); } } catch (ProtocolException ex) { exception = ex; } Assumes.NotNull(exception); // 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 (UntrustedWebRequestHandler.IsExceptionFrom417ExpectationFailed(exception)) { return(await this.CreateNewAssociationAsync(provider, associateRequest, retriesRemaining - 1, cancellationToken)); } // 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.Uri, exception); return(null); }