Пример #1
0
        internal string SaveTokenDataToDatabase()
        {
            var tokenKey       = Guid.NewGuid();
            var samlXml        = SamlHelpers.ConvertToString(this);
            var encryptedToken = SamlHelpers.Protect(samlXml, GetType().Name);

            SqlData.SaveEncryptedSamlToken(tokenKey, encryptedToken);

            return(tokenKey.ToString());
        }
Пример #2
0
        internal string GetReturnUrl()
        {
            string returnUrl = SamlHelpers.GetCookieReturnUrl();

            SamlHelpers.ClearCookieReturnUrl();

            if (string.IsNullOrEmpty(returnUrl))
            {
                returnUrl = Apis.Get <IUrl>().Absolute(Apis.Get <ICoreUrls>().Home());
            }

            return(returnUrl);
        }
Пример #3
0
        internal string SaveToSecureCookie()
        {
            var    tokenKey       = Guid.NewGuid();
            string samlXml        = SamlHelpers.ConvertToString(this);
            var    encryptedToken = SamlHelpers.Protect(samlXml, this.GetType().Name);

            HttpCookie cookie = new HttpCookie(tokenKey.ToString(), encryptedToken);

            cookie.HttpOnly = true;
            cookie.Secure   = HttpContext.Current.Request.IsSecureConnection;

            CookieHelper.AddCookie(cookie);

            return(tokenKey.ToString());
        }
Пример #4
0
 internal static SamlTokenData GetFromSecureCookie(string tokenKey)
 {
     try
     {
         HttpCookie secureCookie  = CookieHelper.GetCookie(tokenKey);
         var        samlXml       = SamlHelpers.Unprotect(secureCookie.Value, typeof(SamlTokenData).Name);
         var        samlTokenData = SamlHelpers.Deserialize <SamlTokenData>(samlXml);
         return(samlTokenData);
     }
     catch (Exception ex)
     {
         Apis.Get <IEventLog>().Write("Error Extracting SAML token from cookie:" + ex, new EventLogEntryWriteOptions {
             Category = "SAML", EventType = "Error", EventId = 1001
         });
     }
     return(null);
 }
Пример #5
0
        internal static SamlTokenData GetTokenDataFromDatabase(string tokenKey)
        {
            try
            {
                var encryptedData = SqlData.GetTokenData(tokenKey);
                if (!string.IsNullOrEmpty(encryptedData))
                {
                    var samlXml       = SamlHelpers.Unprotect(encryptedData, typeof(SamlTokenData).Name);
                    var samlTokenData = SamlHelpers.Deserialize <SamlTokenData>(samlXml);
                    return(samlTokenData);
                }
            }
            catch (Exception ex)
            {
                ApiEventLog.Write("Error Extracting SAML token from database:" + ex, new EventLogEntryWriteOptions()
                {
                    Category = "SAML", EventType = "Error", EventId = 1001
                });
            }

            return(null);
        }
Пример #6
0
        public void ProcessRequest(HttpContext context)
        {
            string returnUrl = "/";

            //protect against no httpcontext or cs context
            try
            {
                //exclude logout and register urls from setting the return url
                //grab the invitation key
                Guid?invitationKey = null;
                Guid parsedInvitationKey;
                //add user invitation guid if present...
                var i = SamlHelpers.GetInvitationKey();
                if (i != null)
                {
                    if (Guid.TryParse(i, out parsedInvitationKey))
                    {
                        invitationKey = parsedInvitationKey;
                    }
                }
                //note we still have the case where the invitation may be in the return url

                var returnUrlParam = context.Request.QueryString[SamlHelpers.ReturnUrlParameterName];
                if (IsValidReturnUrl(returnUrlParam)) //ignores pages like logout or register or errors
                {
                    returnUrl = context.Request[SamlHelpers.ReturnUrlParameterName];
                    //if there is more than one return url, just use the first
                    returnUrl = returnUrl.Split(',')[0];
                }
                SamlHelpers.SetCookieReturnUrl(returnUrl, invitationKey);
            }
            catch (Exception ex)
            {
                Apis.Get <IEventLog>().Write("Error Creating SAML return URL cookie:" + ex, new EventLogEntryWriteOptions {
                    Category = "SAML", EventType = "Error", EventId = 1000
                });
            }


            var samlPlugin = PluginManager.GetSingleton <SamlOAuthClient>();

            if (samlPlugin == null)
            {
                throw new InvalidOperationException("Unable to load the SamlAuthentication plugin; saml logins are not supported in the current configuration");
            }

            var requestId = "_" + Guid.NewGuid().ToString();
            var issuerUrl = Apis.Get <IUrl>().Absolute(Apis.Get <ICoreUrls>().Home());


            //if (samlPlugin.IdpBindingType == SamlBinding.SAML11_POST && (samlPlugin.IdpAuthRequestType != AuthnBinding.IDP_Initiated) || (samlPlugin.IdpAuthRequestType != AuthnBinding.WSFededation))
            //    throw new NotSupportedException("Only bare get requests (without querystring or signature) are supported by the SAML 11 AuthN handler at this time");


            switch (samlPlugin.IdpAuthRequestType)
            {
            case AuthnBinding.WSFededation:
                context.Response.Redirect(string.Format(WsFederationSignInTemplate, samlPlugin.IdpUrl, HttpUtility.UrlEncode(Apis.Get <IUrl>().Absolute("~/")), HttpUtility.UrlEncode(Apis.Get <IUrl>().Absolute("~/samlresponse"))));
                HttpContext.Current.ApplicationInstance.CompleteRequest();
                break;

            case AuthnBinding.IDP_Initiated:
                context.Response.Redirect(samlPlugin.IdpUrl, false);
                HttpContext.Current.ApplicationInstance.CompleteRequest();
                break;

            case AuthnBinding.Redirect:     //untested
                context.Response.Redirect(samlPlugin.IdpUrl + "?SAMLRequest=" + HttpUtility.UrlEncode(System.Text.Encoding.Default.GetString(ZipStr(GetSamlAuthnBase64(requestId, samlPlugin.IdpUrl, issuerUrl)))) + "&RelayState=" + HttpUtility.UrlEncode("/SamlLogin?ReturnUrl=" + returnUrl), false);
                HttpContext.Current.ApplicationInstance.CompleteRequest();
                break;

            case AuthnBinding.SignedRedirect:
                var redirectThumbprint = samlPlugin.AuthNCertThumbrint;

                if (string.IsNullOrEmpty(redirectThumbprint))
                {
                    throw new ArgumentNullException("Invalid configuration, the SAML Plugin is set to sign AuthN requests, but no certificate thumbprint is configured", "samlPlugin.AuthNCertThumbrint");
                }

                throw new NotImplementedException();
            //break;

            case AuthnBinding.POST:
                var authXML = GetSamlAuthnXml(requestId, samlPlugin.IdpUrl, issuerUrl);
                ValidateXML(authXML);
                POSTAuthNRequest(samlPlugin.IdpUrl, authXML);
                break;

            case AuthnBinding.SignedPOST:
                var postThumbprint = samlPlugin.AuthNCertThumbrint;

                if (string.IsNullOrEmpty(postThumbprint))
                {
                    throw new ArgumentNullException("Invalid configuration, the SAML Plugin is set to sign AuthN requests, but no certificate thumbprint is configured", "samlPlugin.AuthNCertThumbrint");
                }


                var signedAuthXML = GetSamlAuthnXml(requestId, samlPlugin.IdpUrl, issuerUrl, postThumbprint);
                ValidateXML(signedAuthXML);
                POSTAuthNRequest(samlPlugin.IdpUrl, signedAuthXML);
                break;
            }
        }
Пример #7
0
        public override string GetIssuerName(SecurityToken securityToken)
        {
            if (securityToken == null)
            {
                throw new ArgumentNullException("securityToken");
            }
            X509SecurityToken token = securityToken as X509SecurityToken;

            if (token != null)
            {
                string thumbprint = token.Certificate.Thumbprint;

                if (this._configuredTrustedIssuers.ContainsKey(thumbprint))
                {
                    string str2 = this._configuredTrustedIssuers[thumbprint];
                    str2 = string.IsNullOrEmpty(str2) ? token.Certificate.Subject : str2;
                    return(str2);
                }


                throw new KeyNotFoundException(string.Format("Could not find Thumbprint '{0}' in trusted issuers list : {1}  :: Char Codes {2} vs {3}", thumbprint, string.Join(",", _configuredTrustedIssuers.Keys.ToArray <string>()), SamlHelpers.ToCompositeString(thumbprint), SamlHelpers.ToCompositeString(string.Join(",", _configuredTrustedIssuers.Keys.ToArray <string>()))));
            }

            //Throw our own exception to make it easier to debug
            throw new ArgumentException("Unable to validate token issuer the provided token was not a X509SecurityToken; cant determine the thumbprint to match", "securityToken");
        }
Пример #8
0
        public void ProcessRequest(HttpContext context)
        {
            var samlPlugin = PluginManager.GetSingleton <SamlOAuthClient>();

            if (samlPlugin == null || !samlPlugin.Enabled)
            {
                throw new InvalidOperationException("Unable to load the SamlAuthentication plugin; saml logins are not supported in the current configuration");
            }

            if (SamlHelpers.IsSignInResponse)
            {
                //use httpcontextuser is set to true, so this code below will only ever fire if there is a HttpContextUser set
                SamlTokenData samlTokenData = null;

                if (!SamlHelpers.IsSignInResponse)
                {
                    throw new NotSupportedException("Unable to detect a saml response; please check your identity provider is configured properly");
                }

                //This call gets the saml token from the response, validates it and turns it into our internal class for use and storage
                samlTokenData = samlPlugin.TokenProcessor.GetSamlTokenData();

                if (samlTokenData == null)
                {
                    throw new InvalidOperationException("No valid saml token was decected, login failed");
                }

                if (samlTokenData.IsExistingUser())
                {
                    if (samlPlugin.PersistClaims)
                    {
                        SqlData.SaveSamlToken(samlTokenData);
                    }

                    //since new users will have oauth links auto created, we only run this code for existing users
                    var samlOAuthLinkManager = PluginManager.GetSingleton <ISamlOAuthLinkManager>();
                    if (samlOAuthLinkManager != null && samlOAuthLinkManager.Enabled)
                    {
                        // makes sure the user is not prompted to "link accounts" during the login form
                        //if there is no suitable entry in the te_OAuth_Links table
                        samlOAuthLinkManager.EnsureOAuthLink(samlTokenData);
                    }
                }

                //Store out the SAML Token Data in an encrypted cookie for use on the OAuth endpoint which requires a GET request
                //var tokenKey = samlTokenData.SaveToSecureCookie();
                //Store out the SAML Token Data in a table on the database for use in the OAuth endpoint which requires a GET request
                //This was added to prevent issues with cookie size - Tony Triguero 2/14/2019
                var tokenKey = samlTokenData.SaveTokenDataToDatabase();

                //build the oauth url based on the current url
                UriBuilder oAuthUrl = new UriBuilder(context.Request.Url);
                oAuthUrl.Path = oAuthUrl.Path.Replace("samlresponse/", string.Format("oauth", samlPlugin.ClientType)).Replace("samlresponse", string.Format("oauth", samlPlugin.ClientType));

                var queryString = HttpUtility.ParseQueryString(oAuthUrl.Query);

                queryString.Add("type", samlPlugin.ClientType);
                queryString.Add(SamlOAuthClient.oauthTokeyQuerystringKey, tokenKey.ToString());

                //Invitation Key
                string invitationKey = SamlHelpers.GetInvitationKey();
                if (!String.IsNullOrEmpty(invitationKey) && !queryString.ToString().ToLower().Contains("invitationkey="))
                {
                    queryString.Add(SamlHelpers.InvitationKeyParameterName, invitationKey);
                }

                //Return Url  (note this must return back to the login page, the actual final return url should be double encoded)
                string returnUrl = GetReturnUrl();
                if (!String.IsNullOrEmpty(returnUrl) && !queryString.ToString().ToLower().Contains("returnurl="))
                {
                    queryString.Add(SamlHelpers.ReturnUrlParameterName, string.Format("{0}&{1}={2}", samlPlugin.CallbackUrl, SamlHelpers.ReturnUrlParameterName, returnUrl)); //the ToString of the queryString object will properly encode the &ReturnUrl
                }
                oAuthUrl.Query = queryString.ToString();

                //Ensure HTTPS so our secure cookie can be read
                if (samlPlugin.SecureCookie || HttpContext.Current.Request.IsSecureConnection)
                {
                    oAuthUrl.Scheme = Uri.UriSchemeHttps;
                    oAuthUrl.Port   = -1; // default port for scheme
                }

                //redirect to the oauth endpoint
                var url = oAuthUrl.Uri.AbsoluteUri;
                context.Response.Redirect(oAuthUrl.Uri.AbsoluteUri);
                context.ApplicationInstance.CompleteRequest();
                context.Response.End();
            }
            else if (SamlHelpers.IsSignOutResponse)
            {
                var platformLogout = PluginManager.GetSingleton <IPlatformLogout>();
                if (platformLogout == null || !platformLogout.Enabled)
                {
                    throw new NotSupportedException("Unable to support WSFederation logouts without an appropriate IPlatformLogout plugin");
                }

                platformLogout.Logout();

                context.Response.Clear();
                context.Response.Buffer = true;
                // Read the original file from disk
                Stream myFileStream = EmbeddedResources.GetStream("Telligent.Services.SamlAuthenticationPlugin.Resources.Images.oauth.gif");
                long   FileSize     = myFileStream.Length;
                byte[] Buffer       = new byte[(int)FileSize];
                myFileStream.Read(Buffer, 0, (int)FileSize);
                myFileStream.Close();

                // Tell the browser stuff about the file
                context.Response.AddHeader("Content-Length", FileSize.ToString());
                context.Response.AddHeader("Content-Disposition", "inline; filename=oauth.gif");
                context.Response.ContentType = "image/gif";

                // Send the data to the browser
                context.Response.BinaryWrite(Buffer);
                context.ApplicationInstance.CompleteRequest();
                context.Response.End();
                return;
            }

            //if this is not a sign-in response, we should probably redirect to login.aspx
            throw new ArgumentException("The SAML token was not found in the HttpContext.Current.Request, please check the configuration and try again");
        }