public static AssociateRequest Create(OpenIdRelyingParty relyingParty, ServiceEndpoint provider) { if (relyingParty == null) { throw new ArgumentNullException("relyingParty"); } if (provider == null) { throw new ArgumentNullException("provider"); } string assoc_type, session_type; bool requireDiffieHellman = !string.Equals(provider.ProviderEndpoint.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase); if (HmacShaAssociation.TryFindBestAssociation(provider.Protocol, relyingParty.Settings.MinimumHashBitLength, relyingParty.Settings.MaximumHashBitLength, requireDiffieHellman, out assoc_type, out session_type)) { return(Create(relyingParty, provider, assoc_type, session_type, true)); } else { // 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); } }
public AssociateResponse(OpenIdRelyingParty relyingParty, ServiceEndpoint provider, IDictionary <string, string> args, DiffieHellman dh) : base(relyingParty, provider, args) { DH = dh; if (Args.ContainsKey(Protocol.openidnp.assoc_handle)) { initializeAssociation(); } else { // Attempt to recover from an unsupported assoc_type if (Protocol.Version.Major >= 2) { if (Util.GetRequiredArg(Args, Protocol.openidnp.error_code) == Protocol.Args.ErrorCode.UnsupportedType) { string assoc_type = Util.GetRequiredArg(Args, Protocol.openidnp.assoc_type); string session_type = Util.GetRequiredArg(Args, Protocol.openidnp.session_type); // If the suggested options are among those we support... if (Array.IndexOf(Protocol.Args.SignatureAlgorithm.All, assoc_type) >= 0 && Array.IndexOf(Protocol.Args.SessionType.All, session_type) >= 0 && RelyingParty.Settings.IsAssociationInPermittedRange(Protocol, assoc_type)) { SecondAttempt = AssociateRequest.Create(RelyingParty, Provider, assoc_type, session_type, false); } } } } }
protected DirectResponse(OpenIdRelyingParty relyingParty, ServiceEndpoint provider, IDictionary <string, string> args) { if (relyingParty == null) { throw new ArgumentNullException("relyingParty"); } if (provider == null) { throw new ArgumentNullException("provider"); } if (args == null) { throw new ArgumentNullException("args"); } RelyingParty = relyingParty; Provider = provider; Args = args; // Make sure that the OP fulfills the required OpenID version. // We don't use Provider.Protocol here because that's just a cache of // what we _thought_ the OP would support, and our purpose is to double-check this. ProtocolVersion detectedProtocol = Protocol.DetectFromDirectResponse(args).ProtocolVersion; if (detectedProtocol < relyingParty.Settings.MinimumRequiredOpenIdVersion) { throw new OpenIdException(string.Format(CultureInfo.CurrentCulture, Strings.MinimumOPVersionRequirementNotMet, Protocol.Lookup(relyingParty.Settings.MinimumRequiredOpenIdVersion).Version, Protocol.Lookup(detectedProtocol).Version)); } }
AuthenticationRequest(ServiceEndpoint endpoint, Realm realm, Uri returnToUrl, OpenIdRelyingParty relyingParty) { if (endpoint == null) { throw new ArgumentNullException("endpoint"); } if (realm == null) { throw new ArgumentNullException("realm"); } if (returnToUrl == null) { throw new ArgumentNullException("returnToUrl"); } if (relyingParty == null) { throw new ArgumentNullException("relyingParty"); } this.endpoint = endpoint; RelyingParty = relyingParty; Realm = realm; ReturnToUrl = returnToUrl; Mode = AuthenticationRequestMode.Setup; OutgoingExtensions = ExtensionArgumentsManager.CreateOutgoingExtensions(endpoint.Protocol); ReturnToArgs = new Dictionary <string, string>(); }
static AuthenticationResponse parseIdResResponse(IDictionary <string, string> query, ServiceEndpoint tokenEndpoint, ServiceEndpoint responseEndpoint, OpenIdRelyingParty relyingParty, Uri requestUrl, bool verifyMessageSignature) { // Use responseEndpoint if it is available so we get the // Claimed Identifer correct in the AuthenticationResponse. ServiceEndpoint unverifiedEndpoint = responseEndpoint ?? tokenEndpoint; if (unverifiedEndpoint.Protocol.Version.Major < 2) { string user_setup_url = Util.GetOptionalArg(query, unverifiedEndpoint.Protocol.openid.user_setup_url); if (user_setup_url != null) { return(new AuthenticationResponse(AuthenticationStatus.SetupRequired, unverifiedEndpoint, query)); } } verifyReturnTo(query, unverifiedEndpoint, requestUrl); verifyDiscoveredInfoMatchesAssertedInfo(relyingParty, query, tokenEndpoint, responseEndpoint); if (verifyMessageSignature) { verifyNonceUnused(query, unverifiedEndpoint, relyingParty.Store); verifySignature(relyingParty, query, unverifiedEndpoint); } return(new AuthenticationResponse(AuthenticationStatus.Authenticated, unverifiedEndpoint, query)); }
/// <summary> /// Performs request generation for the <see cref="Create"/> method. /// All data validation and cleansing steps must have ALREADY taken place. /// </summary> private static IEnumerable <AuthenticationRequest> CreateInternal(Identifier userSuppliedIdentifier, OpenIdRelyingParty relyingParty, Realm realm, Uri returnToUrl, IEnumerable <ServiceEndpoint> serviceEndpoints, bool createNewAssociationsAsNeeded) { //Logger.InfoFormat("Performing discovery on user-supplied identifier: {0}", userSuppliedIdentifier); IEnumerable <ServiceEndpoint> endpoints = filterAndSortEndpoints(serviceEndpoints, relyingParty); // Maintain a list of endpoints that we could not form an association with. // We'll fallback to generating requests to these if the ones we CAN create // an association with run out. var failedAssociationEndpoints = new List <ServiceEndpoint>(0); foreach (var endpoint in endpoints) { //Logger.InfoFormat("Creating authentication request for user supplied Identifier: {0}", userSuppliedIdentifier); //Logger.DebugFormat("Realm: {0}", realm); //Logger.DebugFormat("Return To: {0}", returnToUrl); // The strategy here is to prefer endpoints with whom we can create associations. Association association = null; if (relyingParty.Store != null) { // In some scenarios (like the AJAX control wanting ALL auth requests possible), // we don't want to create associations with every Provider. But we'll use // associations where they are already formed from previous authentications. association = getAssociation(relyingParty, endpoint, createNewAssociationsAsNeeded); if (association == null && createNewAssociationsAsNeeded) { //Logger.WarnFormat("Failed to create association with {0}. Skipping to next endpoint.", endpoint.ProviderEndpoint); // No association could be created. Add it to the list of failed association // endpoints and skip to the next available endpoint. failedAssociationEndpoints.Add(endpoint); continue; } } yield return(new AuthenticationRequest(endpoint, realm, returnToUrl, relyingParty)); } // Now that we've run out of endpoints that respond to association requests, // since we apparently are still running, the caller must want another request. // We'll go ahead and generate the requests to OPs that may be down. if (failedAssociationEndpoints.Count > 0) { //Logger.WarnFormat("Now generating requests for Provider endpoints that failed initial association attempts."); foreach (var endpoint in failedAssociationEndpoints) { //Logger.WarnFormat("Creating authentication request for user supplied Identifier: {0}", userSuppliedIdentifier); //Logger.DebugFormat("Realm: {0}", realm); //Logger.DebugFormat("Return To: {0}", returnToUrl); // Create the auth request, but prevent it from attempting to create an association // because we've already tried. Let's not have it waste time trying again. var authRequest = new AuthenticationRequest(endpoint, realm, returnToUrl, relyingParty); authRequest.associationPreference = AssociationPreference.IfAlreadyEstablished; yield return(authRequest); } } }
/// <summary> /// Performs a dumb-mode authentication verification by making an extra /// request to the provider after the user agent was redirected back /// to the consumer site with an authenticated status. /// </summary> /// <returns>Whether the authentication is valid.</returns> static void verifySignatureByProvider(OpenIdRelyingParty relyingParty, IDictionary <string, string> query, ServiceEndpoint provider) { var request = CheckAuthRequest.Create(relyingParty, provider, query); if (request.Response.InvalidatedAssociationHandle != null && relyingParty.Store != null) { relyingParty.Store.RemoveAssociation(provider.ProviderEndpoint, request.Response.InvalidatedAssociationHandle); } if (!request.Response.IsAuthenticationValid) { throw new OpenIdException(Strings.InvalidSignature); } }
static void verifySignature(OpenIdRelyingParty relyingParty, IDictionary <string, string> query, ServiceEndpoint endpoint) { string signed = Util.GetRequiredArg(query, endpoint.Protocol.openid.signed); string[] signedFields = signed.Split(','); // Check that all fields that are required to be signed are indeed signed if (endpoint.Protocol.Version.Major >= 2) { verifyFieldsAreSigned(signedFields, endpoint.Protocol.openidnp.op_endpoint, endpoint.Protocol.openidnp.return_to, endpoint.Protocol.openidnp.response_nonce, endpoint.Protocol.openidnp.assoc_handle); if (query.ContainsKey(endpoint.Protocol.openid.claimed_id)) { verifyFieldsAreSigned(signedFields, endpoint.Protocol.openidnp.claimed_id, endpoint.Protocol.openidnp.identity); } } else { verifyFieldsAreSigned(signedFields, endpoint.Protocol.openidnp.identity, endpoint.Protocol.openidnp.return_to); } // Now actually validate the signature itself. string assoc_handle = Util.GetRequiredArg(query, endpoint.Protocol.openid.assoc_handle); Association assoc = relyingParty.Store != null?relyingParty.Store.GetAssociation(endpoint.ProviderEndpoint, assoc_handle) : null; if (assoc == null) { // It's not an association we know about. Dumb mode is our // only possible path for recovery. //Logger.Debug("Passing signature back to Provider for verification (no association available)..."); verifySignatureByProvider(relyingParty, query, endpoint); } else { if (assoc.IsExpired) { throw new OpenIdException(string.Format(CultureInfo.CurrentCulture, "Association with {0} expired", endpoint.ProviderEndpoint), endpoint.ClaimedIdentifier); } //Logger.Debug("Verifying signature by association..."); verifySignatureByAssociation(query, endpoint.Protocol, signedFields, assoc); } }
/// <summary> /// Returns a filtered and sorted list of the available OP endpoints for a discovered Identifier. /// </summary> private static List <ServiceEndpoint> filterAndSortEndpoints(IEnumerable <ServiceEndpoint> endpoints, OpenIdRelyingParty relyingParty) { if (endpoints == null) { throw new ArgumentNullException("endpoints"); } if (relyingParty == null) { throw new ArgumentNullException("relyingParty"); } // Construct the endpoints filters based on criteria given by the host web site. EndpointSelector versionFilter = ep => ((ServiceEndpoint)ep).Protocol.Version >= Protocol.Lookup(relyingParty.Settings.MinimumRequiredOpenIdVersion).Version; EndpointSelector hostingSiteFilter = relyingParty.EndpointFilter ?? (ep => true); bool anyFilteredOut = false; var filteredEndpoints = new List <IXrdsProviderEndpoint>(); foreach (ServiceEndpoint endpoint in endpoints) { if (versionFilter(endpoint) && hostingSiteFilter(endpoint)) { filteredEndpoints.Add(endpoint); } else { anyFilteredOut = true; } } // Sort endpoints so that the first one in the list is the most preferred one. filteredEndpoints.Sort(relyingParty.EndpointOrder); List <ServiceEndpoint> endpointList = new List <ServiceEndpoint>(filteredEndpoints.Count); foreach (ServiceEndpoint endpoint in filteredEndpoints) { endpointList.Add(endpoint); } if (anyFilteredOut) { //Logger.DebugFormat("Some endpoints were filtered out. Total endpoints remaining: {0}", filteredEndpoints.Count); } return(endpointList); }
/// <summary> /// Performs identifier discovery and creates associations and generates authentication requests /// on-demand for as long as new ones can be generated based on the results of Identifier discovery. /// </summary> internal static IEnumerable <AuthenticationRequest> Create(Identifier userSuppliedIdentifier, OpenIdRelyingParty relyingParty, Realm realm, Uri returnToUrl, bool createNewAssociationsAsNeeded) { // We have a long data validation and preparation process if (userSuppliedIdentifier == null) { throw new ArgumentNullException("userSuppliedIdentifier"); } if (relyingParty == null) { throw new ArgumentNullException("relyingParty"); } if (realm == null) { throw new ArgumentNullException("realm"); } userSuppliedIdentifier = userSuppliedIdentifier.TrimFragment(); if (relyingParty.Settings.RequireSsl) { // Rather than check for successful SSL conversion at this stage, // We'll wait for secure discovery to fail on the new identifier. userSuppliedIdentifier.TryRequireSsl(out userSuppliedIdentifier); } //Logger.InfoFormat("Creating authentication request for user supplied Identifier: {0}", // userSuppliedIdentifier); //Logger.DebugFormat("Realm: {0}", realm); //Logger.DebugFormat("Return To: {0}", returnToUrl); //Logger.DebugFormat("RequireSsl: {0}", userSuppliedIdentifier.IsDiscoverySecureEndToEnd); // Throw an exception now if the realm and the return_to URLs don't match // as required by the provider. We could wait for the provider to test this and // fail, but this will be faster and give us a better error message. if (!realm.Contains(returnToUrl)) { throw new OpenIdException(string.Format(CultureInfo.CurrentCulture, Strings.ReturnToNotUnderRealm, returnToUrl, realm)); } // Perform discovery right now (not deferred). var serviceEndpoints = userSuppliedIdentifier.Discover(); // Call another method that defers request generation. return(CreateInternal(userSuppliedIdentifier, relyingParty, realm, returnToUrl, serviceEndpoints, createNewAssociationsAsNeeded)); }
public static CheckAuthRequest Create(OpenIdRelyingParty relyingParty, ServiceEndpoint provider, IDictionary <string, string> query) { if (relyingParty == null) { throw new ArgumentNullException("relyingParty"); } Protocol protocol = provider.Protocol; string signed = query[protocol.openid.signed]; if (signed == null) { // #XXX: oidutil.log('No signature present; checkAuth aborted') return(null); } // Arguments that are always passed to the server and not // included in the signature. string[] whitelist = new string[] { protocol.openidnp.assoc_handle, protocol.openidnp.sig, protocol.openidnp.signed, protocol.openidnp.invalidate_handle }; string[] splitted = signed.Split(','); // combine the previous 2 arrays (whitelist + splitted) into a new array: signed_array string[] signed_array = new string[whitelist.Length + splitted.Length]; Array.Copy(whitelist, signed_array, whitelist.Length); Array.Copy(splitted, 0, signed_array, whitelist.Length, splitted.Length); var check_args = new Dictionary <string, string>(); foreach (string key in query.Keys) { if (key.StartsWith(protocol.openid.Prefix, StringComparison.OrdinalIgnoreCase) && Array.IndexOf(signed_array, key.Substring(protocol.openid.Prefix.Length)) > -1) { check_args[key] = query[key]; } } check_args[protocol.openid.mode] = protocol.Args.Mode.check_authentication; return(new CheckAuthRequest(relyingParty, provider, check_args)); }
protected DirectRequest(OpenIdRelyingParty relyingParty, ServiceEndpoint provider, IDictionary <string, string> args) { if (relyingParty == null) { throw new ArgumentNullException("relyingParty"); } if (provider == null) { throw new ArgumentNullException("provider"); } if (args == null) { throw new ArgumentNullException("args"); } RelyingParty = relyingParty; Provider = provider; Args = args; if (Protocol.QueryDeclaredNamespaceVersion != null && !Args.ContainsKey(Protocol.openid.ns)) { Args.Add(Protocol.openid.ns, Protocol.QueryDeclaredNamespaceVersion); } }
public CheckAuthResponse(OpenIdRelyingParty relyingParty, ServiceEndpoint provider, IDictionary <string, string> args) : base(relyingParty, provider, args) { }
static Association getAssociation(OpenIdRelyingParty relyingParty, ServiceEndpoint provider, bool createNewAssociationIfNeeded) { if (relyingParty == null) { throw new ArgumentNullException("relyingParty"); } if (provider == null) { throw new ArgumentNullException("provider"); } // If the RP has no application store for associations, there's no point in creating one. if (relyingParty.Store == null) { return(null); } // TODO: we need a way to lookup an association that fulfills a given set of security // requirements. We may have a SHA-1 association and a SHA-256 association that need // to be called for specifically. (a bizzare scenario, admittedly, making this low priority). Association assoc = relyingParty.Store.GetAssociation(provider.ProviderEndpoint); // If the returned association does not fulfill security requirements, ignore it. if (assoc != null && !relyingParty.Settings.IsAssociationInPermittedRange(provider.Protocol, assoc.GetAssociationType(provider.Protocol))) { assoc = null; } if ((assoc == null || !assoc.HasUsefulLifeRemaining) && createNewAssociationIfNeeded) { var req = AssociateRequest.Create(relyingParty, provider); if (req == null) { // this can happen if security requirements and protocol conflict // to where there are no association types to choose from. return(null); } if (req.Response != null) { // try again if we failed the first time and have a worthy second-try. if (req.Response.Association == null && req.Response.SecondAttempt != null) { //Logger.Warn("Initial association attempt failed, but will retry with Provider-suggested parameters."); req = req.Response.SecondAttempt; } assoc = req.Response.Association; // Confirm that the association matches the type we requested (section 8.2.1) // if this is a 2.0 OP (1.x OPs had freedom to differ from the requested type). if (assoc != null && provider.Protocol.Version.Major >= 2) { if (!string.Equals( req.Args[provider.Protocol.openid.assoc_type], Util.GetRequiredArg(req.Response.Args, provider.Protocol.openidnp.assoc_type), StringComparison.Ordinal) || !string.Equals( req.Args[provider.Protocol.openid.session_type], Util.GetRequiredArg(req.Response.Args, provider.Protocol.openidnp.session_type), StringComparison.Ordinal)) { //Logger.ErrorFormat("Provider responded with contradicting association parameters. Requested [{0}, {1}] but got [{2}, {3}] back.", // req.Args[provider.Protocol.openid.assoc_type], // req.Args[provider.Protocol.openid.session_type], // Util.GetRequiredArg(req.Response.Args, provider.Protocol.openidnp.assoc_type), // Util.GetRequiredArg(req.Response.Args, provider.Protocol.openidnp.session_type)); assoc = null; } } if (assoc != null) { //Logger.InfoFormat("Association with {0} established.", provider.ProviderEndpoint); relyingParty.Store.StoreAssociation(provider.ProviderEndpoint, assoc); } else { //Logger.ErrorFormat("Association attempt with {0} provider failed.", provider.ProviderEndpoint); } } } return(assoc); }
/// <summary> /// Instantiates an <see cref="AssociateRequest"/> object. /// </summary> /// <param name="relyingParty">The RP instance that is creating this request.</param> /// <param name="provider">The discovered OpenID Provider endpoint information.</param> /// <param name="args">The arguments assembled for sending to the Provider.</param> /// <param name="dh">Optional. Supplied only if Diffie-Hellman is used for encrypting the association secret key.</param> AssociateRequest(OpenIdRelyingParty relyingParty, ServiceEndpoint provider, IDictionary <string, string> args, DiffieHellman dh) : base(relyingParty, provider, args) { DH = dh; }
/// <remarks> /// This is documented in OpenId Authentication 2.0 section 11.2. /// </remarks> static void verifyDiscoveredInfoMatchesAssertedInfo(OpenIdRelyingParty relyingParty, IDictionary <string, string> query, ServiceEndpoint tokenEndpoint, ServiceEndpoint responseEndpoint) { //Logger.Debug("Verifying assertion matches identifier discovery results..."); // Verify that the actual version of the OP endpoint matches discovery. Protocol actualProtocol = Protocol.Detect(query); Protocol discoveredProtocol = (tokenEndpoint ?? responseEndpoint).Protocol; if (!actualProtocol.Equals(discoveredProtocol)) { // Allow an exception so that v1.1 and v1.0 can be seen as identical for this // verification. v1.0 has no spec, and v1.1 and v1.0 cannot be clearly distinguished // from the protocol, so detecting their differences is meaningless, and throwing here // would just break thing unnecessarily. if (!(actualProtocol.Version.Major == 1 && discoveredProtocol.Version.Major == 1)) { throw new OpenIdException(string.Format(CultureInfo.CurrentCulture, Strings.OpenIdDiscoveredAndActualVersionMismatch, actualProtocol.Version, discoveredProtocol.Version)); } } if ((tokenEndpoint ?? responseEndpoint).Protocol.Version.Major < 2) { Debug.Assert(tokenEndpoint != null, "Our OpenID 1.x implementation requires an RP token. And this should have been verified by our caller."); // For 1.x OPs, we only need to verify that the OP Local Identifier // hasn't changed since we made the request. if (tokenEndpoint.ProviderLocalIdentifier != Util.GetRequiredArg(query, tokenEndpoint.Protocol.openid.identity)) { throw new OpenIdException(string.Format(CultureInfo.CurrentCulture, Strings.TamperingDetected, tokenEndpoint.Protocol.openid.identity, tokenEndpoint.ProviderLocalIdentifier, Util.GetRequiredArg(query, tokenEndpoint.Protocol.openid.identity))); } } else { // In 2.0, we definitely have a responseEndpoint, but may not have a // tokenEndpoint. If we don't have a tokenEndpoint, or it doesn't match the assertion, // or if the user gave us an OP Identifier originally, then we need to perform discovery on // the responseEndpoint.ClaimedIdentifier to verify the OP has authority // to speak for it. if (tokenEndpoint == null || // no token included (unsolicited assertion) tokenEndpoint != responseEndpoint || // the OP is asserting something different than we asked for tokenEndpoint.ClaimedIdentifier == tokenEndpoint.Protocol.ClaimedIdentifierForOPIdentifier) // or directed identity is in effect { Identifier claimedIdentifier = Util.GetRequiredArg(query, responseEndpoint.Protocol.openid.claimed_id); // Require SSL where appropriate. This will filter out insecure identifiers, // redirects and provider endpoints automatically. If we find a match after all that // filtering with the responseEndpoint, then the unsolicited assertion is secure. if (relyingParty.Settings.RequireSsl && !claimedIdentifier.TryRequireSsl(out claimedIdentifier)) { throw new OpenIdException(Strings.InsecureWebRequestWithSslRequired, query); } //Logger.InfoFormat("Provider asserted an identifier that requires (re)discovery to confirm."); List <ServiceEndpoint> discoveredEndpoints = new List <ServiceEndpoint>(claimedIdentifier.Discover()); // Make sure the response endpoint matches one of the discovered endpoints. if (!discoveredEndpoints.Contains(responseEndpoint)) { throw new OpenIdException(string.Format(CultureInfo.CurrentCulture, Strings.IssuedAssertionFailsIdentifierDiscovery, responseEndpoint, Util.ToString(discoveredEndpoints))); } } } }
internal static AuthenticationResponse Parse(IDictionary <string, string> query, OpenIdRelyingParty relyingParty, Uri requestUrl, bool verifySignature) { if (query == null) { throw new ArgumentNullException("query"); } if (requestUrl == null) { throw new ArgumentNullException("requestUrl"); } //Logger.DebugFormat("OpenID authentication response received:{0}{1}", Environment.NewLine, Util.ToString(query)); ServiceEndpoint tokenEndpoint = null; // The query parameter may be the POST query or the GET query, // but the token parameter will always be in the GET query because // it was added to the return_to parameter list. IDictionary <string, string> requestUrlQuery = Util.NameValueCollectionToDictionary( HttpUtility.ParseQueryString(requestUrl.Query)); string token = Util.GetOptionalArg(requestUrlQuery, Token.TokenKey); if (token != null) { token = FixDoublyUriDecodedToken(token); tokenEndpoint = Token.Deserialize(token, relyingParty.Store).Endpoint; } Protocol protocol = Protocol.Detect(query); string mode = Util.GetRequiredArg(query, protocol.openid.mode); if (mode.Equals(protocol.Args.Mode.cancel, StringComparison.Ordinal)) { return(new AuthenticationResponse(AuthenticationStatus.Canceled, tokenEndpoint, query)); } else if (mode.Equals(protocol.Args.Mode.setup_needed, StringComparison.Ordinal)) { return(new AuthenticationResponse(AuthenticationStatus.SetupRequired, tokenEndpoint, query)); } else if (mode.Equals(protocol.Args.Mode.error, StringComparison.Ordinal)) { throw new OpenIdException(string.Format(CultureInfo.CurrentCulture, "The provider returned an error: {0}", query[protocol.openid.error])); } else if (mode.Equals(protocol.Args.Mode.id_res, StringComparison.Ordinal)) { // We allow unsolicited assertions (that won't have our own token on it) // only for OpenID 2.0 providers. ServiceEndpoint responseEndpoint = null; if (protocol.Version.Major < 2) { if (tokenEndpoint == null) { throw new OpenIdException(string.Format(CultureInfo.CurrentCulture, Strings.MissingInternalQueryParameter, Token.TokenKey)); } } else { // 2.0 OPs provide enough information to assemble the entire endpoint info, // except perhaps for the original user supplied identifier, which if available // allows us to display a friendly XRI. Identifier friendlyIdentifier = tokenEndpoint != null ? tokenEndpoint.UserSuppliedIdentifier : null; responseEndpoint = ServiceEndpoint.ParseFromAuthResponse(query, friendlyIdentifier); // If this is a solicited assertion, we'll have a token with endpoint data too, // which we can use to more quickly confirm the validity of the claimed // endpoint info. } // At this point, we are guaranteed to have tokenEndpoint ?? responseEndpoint // set to endpoint data (one or the other or both). // tokenEndpoint is known good data, whereas responseEndpoint must still be // verified. // For the error-handling and cancellation cases, the info does not have to // be verified, so we'll use whichever one is available. return(parseIdResResponse(query, tokenEndpoint, responseEndpoint, relyingParty, requestUrl, verifySignature)); } else { throw new OpenIdException(string.Format(CultureInfo.CurrentCulture, Strings.InvalidOpenIdQueryParameterValue, protocol.openid.mode, mode), query); } }
public static AssociateRequest Create(OpenIdRelyingParty relyingParty, ServiceEndpoint provider, string assoc_type, string session_type, bool allowNoSession) { if (relyingParty == null) { throw new ArgumentNullException("relyingParty"); } if (provider == null) { throw new ArgumentNullException("provider"); } if (assoc_type == null) { throw new ArgumentNullException("assoc_type"); } if (session_type == null) { throw new ArgumentNullException("session_type"); } Debug.Assert(Array.IndexOf(provider.Protocol.Args.SignatureAlgorithm.All, assoc_type) >= 0); Debug.Assert(Array.IndexOf(provider.Protocol.Args.SessionType.All, session_type) >= 0); if (!HmacShaAssociation.IsDHSessionCompatible(provider.Protocol, assoc_type, session_type)) { throw new OpenIdException(string.Format(CultureInfo.CurrentCulture, Strings.IncompatibleAssociationAndSessionTypes, assoc_type, session_type)); } var args = new Dictionary <string, string>(); Protocol protocol = provider.Protocol; args.Add(protocol.openid.mode, protocol.Args.Mode.associate); args.Add(protocol.openid.assoc_type, assoc_type); DiffieHellman dh = null; if (provider.ProviderEndpoint.Scheme == Uri.UriSchemeHttps && allowNoSession) { //Logger.InfoFormat("Requesting association with {0} (assoc_type = '{1}', session_type = '{2}').", // provider.ProviderEndpoint, assoc_type, protocol.Args.SessionType.NoEncryption); args.Add(protocol.openid.session_type, protocol.Args.SessionType.NoEncryption); } else { //Logger.InfoFormat("Requesting association with {0} (assoc_type = '{1}', session_type = '{2}').", // provider.ProviderEndpoint, assoc_type, session_type); // Initiate Diffie-Hellman Exchange dh = DiffieHellmanUtil.CreateDiffieHellman(); byte[] dhPublic = dh.CreateKeyExchange(); string cpub = DiffieHellmanUtil.UnsignedToBase64(dhPublic); args.Add(protocol.openid.session_type, session_type); args.Add(protocol.openid.dh_consumer_public, cpub); DHParameters dhps = dh.ExportParameters(true); if (dhps.P != DiffieHellmanUtil.DEFAULT_MOD || dhps.G != DiffieHellmanUtil.DEFAULT_GEN) { args.Add(protocol.openid.dh_modulus, DiffieHellmanUtil.UnsignedToBase64(dhps.P)); args.Add(protocol.openid.dh_gen, DiffieHellmanUtil.UnsignedToBase64(dhps.G)); } } return(new AssociateRequest(relyingParty, provider, args, dh)); }