private string ObtainIssuer(string hostname, string resource)
        {
            string query = "/.well-known/webfinger?resource=" + resource + "&rel=http://openid.net/specs/connect/1.0/issuer";

            WebRequest webRequest         = WebRequest.Create(hostname + query);
            Dictionary <string, object> o = WebOperations.GetUrlContent(webRequest);

            if ((DateTime)o["expires"] < DateTime.UtcNow - new TimeSpan(0, 10, 0))
            {
                throw new OIDCException("Claims expired on " + o["expires"]);
            }

            if ((string)o["subject"] != resource)
            {
                throw new OIDCException("Claims released for a different subject.");
            }

            string issuer = null;
            JArray links  = (JArray)o["links"];

            foreach (JToken link in links)
            {
                Dictionary <string, object> dic = link.ToObject <Dictionary <string, object> >();
                if (dic["rel"] as string == "http://openid.net/specs/connect/1.0/issuer")
                {
                    issuer = dic["href"] as string;
                }
            }

            if (issuer == null)
            {
                throw new OIDCException("No issuer found in claims returned.");
            }
            return(issuer);
        }
        public static void ParseAggregatedClaims(OIDCUserInfoResponseMessage obj, Dictionary <string, object> data)
        {
            if (data.ContainsKey("_claim_names") && data["_claim_names"] != null)
            {
                Dictionary <string, object> claims = (data["_claim_names"] as JObject).ToObject <Dictionary <string, object> >();
                foreach (KeyValuePair <string, object> kvp in claims)
                {
                    string name = kvp.Key;
                    string path = kvp.Value.ToString();

                    if (!data.ContainsKey("_claim_sources") || data["_claim_sources"] == null)
                    {
                        continue;
                    }

                    dynamic sources = data["_claim_sources"];
                    foreach (JProperty s in sources)
                    {
                        if (s.Name != path)
                        {
                            continue;
                        }

                        dynamic vals = s.Value;
                        foreach (JProperty v in sources)
                        {
                            Dictionary <string, object> values = null;
                            Dictionary <string, object> val    = (v.Value as JObject).ToObject <Dictionary <string, object> >();

                            if (val.ContainsKey("JWT"))
                            {
                                string json = JWT.Decode(val["JWT"].ToString());
                                values = DeserializeFromJson <Dictionary <string, object> >(json);
                            }
                            else if (val.ContainsKey("endpoint"))
                            {
                                WebRequest req = WebRequest.Create(val["endpoint"].ToString());
                                if (val.ContainsKey("access_token"))
                                {
                                    req.Headers.Add("Authorization", "Bearer " + val["access_token"].ToString());
                                }
                                values = WebOperations.GetUrlContent(req);
                            }

                            if (!values.ContainsKey(name))
                            {
                                continue;
                            }

                            if (obj.CustomClaims == null)
                            {
                                obj.CustomClaims = new Dictionary <string, object>();
                            }
                            obj.CustomClaims[name] = values[name];
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Method that queries the OP server to obtain the OpenID configuration.
        /// </summary>
        /// <param name="hostname">The hostname of the OP to be queried.</param>
        /// <param name="expectedIssuer">(optional) the issuer expected from the OP configuration.
        /// This information can come, for instance, from a previous issuer discovery process
        /// via webfinger.</param>
        /// <returns>An oject describing all relevant properties of the OP.</returns>
        /// <exception cref="OpenIDClient.OIDCException">Thrown when the returned message from server
        /// is not valid or if wrong issuer is found in the answer.</exception>
        public OIDCProviderMetadata ObtainProviderInformation(string hostname, string expectedIssuer = null)
        {
            string     query              = "/.well-known/openid-configuration";
            WebRequest webRequest         = WebRequest.Create(hostname + query);
            Dictionary <string, object> o = WebOperations.GetUrlContent(webRequest);
            OIDCProviderMetadata        providerMetadata = new OIDCProviderMetadata(o);

            if (expectedIssuer != null && !expectedIssuer.Equals(providerMetadata.Issuer))
            {
                throw new OIDCException("Wrong issuer, discarding configuration");
            }

            return(providerMetadata);
        }
        /// <summary>
        /// Constructor deserializing message properties from dictionary.
        /// </summary>
        /// <param name="o">The dictionary object containing message properties.</param>
        public OIDCProviderMetadata(Dictionary <string, object> o)
        {
            DeserializeFromDictionary(o);

            if (JwksUri != null)
            {
                Keys = new List <OIDCKey>();
                Dictionary <string, object> jwks = WebOperations.GetUrlContent(WebRequest.Create(JwksUri));
                JArray keys = (JArray)jwks["keys"];
                foreach (JToken key in keys)
                {
                    OIDCKey newKey = new OIDCKey(key.ToObject <Dictionary <string, object> >());
                    Keys.Add(newKey);
                }
            }
        }
 /// <summary>
 /// Method that sends authentication request to the OP.
 /// </summary>
 /// <param name="AuthenticateUrl">The URL to be used for the authentication request.</param>
 /// <param name="RequestMessage">The reuqest message to be sent to the OP.</param>
 /// <param name="Certificate">The certificate to be used, in case of a self-issued authentication.</param>
 /// <returns>The authentication response from the OP.</returns>
 public OIDCAuthImplicitResponseMessage Authenticate(string AuthenticateUrl, OIDCAuthorizationRequestMessage RequestMessage, X509Certificate2 Certificate = null)
 {
     if (new Uri(AuthenticateUrl).Scheme == "openid")
     {
         // we are dealing with a Self-Issued OpenID provider
         Dictionary <string, object>     response        = PerformSelfIssuedAuthentication(RequestMessage, Certificate);
         OIDCAuthImplicitResponseMessage responseMessage = new OIDCAuthImplicitResponseMessage();
         responseMessage.DeserializeFromDictionary(response);
         return(responseMessage);
     }
     else
     {
         string login_url = AuthenticateUrl + "?" + RequestMessage.SerializeToQueryString();
         WebOperations.GetUrlContent(WebRequest.Create(login_url));
         return(null);
     }
 }
        /// <summary>
        /// Method to perform third party initiated login.
        /// </summary>
        /// <param name="queryString">The query string representation of the authentication request</param>
        /// <param name="authEndpoint">The OP authorization endpoint</param>
        public void ThirdPartyInitiatedLogin(OIDCAuthorizationRequestMessage requestMessage, string authEndpoint)
        {
            string login_url = authEndpoint + "?" + requestMessage.SerializeToQueryString();

            WebOperations.GetUrlContent(WebRequest.Create(login_url));
        }
        /// <summary>
        /// <see cref="OIDClientSerializableMessage.Validate()"/>
        /// </summary>
        public override void Validate()
        {
            if (RedirectUris != null && ResponseTypes != null && RedirectUris.Count != ResponseTypes.Count)
            {
                throw new OIDCException("The redirect_uris do not match response_types.");
            }

            if (RedirectUris != null && SectorIdentifierUri != null)
            {
                List <string> siUris = new List <string>();
                dynamic       uris   = WebOperations.GetUrlContent(WebRequest.Create(SectorIdentifierUri));
                foreach (string uri in uris)
                {
                    siUris.Add(uri);
                }

                foreach (string uri in RedirectUris)
                {
                    if (!siUris.Contains(uri))
                    {
                        throw new OIDCException("The sector_identifier_uri json must include URIs from the redirect_uri array.");
                    }
                }
            }

            if (ResponseTypes != null && GrantTypes != null)
            {
                foreach (ResponseType responseType in ResponseTypes)
                {
                    if ((responseType == ResponseType.Code && !GrantTypes.Contains("authorization_code")) ||
                        (responseType == ResponseType.IdToken && !GrantTypes.Contains("implicit")) ||
                        (responseType == ResponseType.Token && !GrantTypes.Contains("implicit")))
                    {
                        throw new OIDCException("The response_types do not match grant_types.");
                    }
                }
            }

            List <string> listUri = new List <string>()
            {
                LogoUri, ClientUri, PolicyUri, TosUri, JwksUri, SectorIdentifierUri, InitiateLoginUri, RegistrationClientUri
            };

            if (RedirectUris != null)
            {
                listUri.AddRange(RedirectUris);
            }
            if (RequestUris != null)
            {
                listUri.AddRange(RequestUris);
            }

            foreach (string uri in listUri)
            {
                if (uri == null)
                {
                    continue;
                }

                if (new Uri(uri).Scheme != "https")
                {
                    throw new OIDCException("Some of the URIs for the client is not on https");
                }
            }
        }