How to really configure ADFS with Tableau

(As experienced in Server 2012 R2 and Tableau Server 10.2)

TL;DR: Follow Tableau’s guide but use SHA-1 on the ADFS side, and map SAMAccountName to the “email” Outgoing Claim Type

Looking around the web, it seems like using Microsoft’s ADFS with Tableau Server for Single Sign-On (SSO) is widespread and no big deal to setup. Sure, the steps available on Tableau’s site look a little long, but it’s all pretty straightforward. However, there are a couple things that get left out.

The first issue, which has to do with the Secure Hashing Algorithm (SHA) used to sign requests and responses, is easy to mitigate. When I read a support article from Tableau, I got the sense that Tableau should support SHA-256. However, whether I ran the recommended tabadmin command or not, I always ended up with a failed authentication attempt and the following error on the ADFS server:

SAML request is not signed with expected signature algorithm. SAML request is signed with signature algorithm . Expected signature algorithm is

Meanwhile, Tableau Server presented the following error in C:\ProgramData\Tableau\Tableau Server\data\tabsvc\logs\vizportal\vizportal-x.log:

org.opensaml.common.SAMLException: Received response has invalid status code

The fix? Tell ADFS to use SHA-1 for the Tableau relying party. You or your ADFS admin can do this with the following steps (based on Server 2012 R2):

  • Log into the ADFS server
  • Open AD FS Management
  • Go to Trust Relationships -> Relying Party Trusts
  • Double-click the Tableau Relying Party (the identifier column should match what you put in the SAML entity ID field back on your Tableau SAML config)
  • Click the Advanced tab
  • Set the Secure hash algorithm drop-down to SHA-1
  • Click OK

No ADFS restart will be necessary.

Now, of course, there are security implications with this change. SHA-1 is no longer considered secure, so you should first assess the potential risk for your organization.

Onto the second–and potentially more interesting/confounding–issue. Every guide I checked on how to configure ADFS listed the following attributes in the claims rule:

  • SAM-Account-Name -> Name ID
  • SAM-Account-Name -> username
  • (optional) Surname -> LastName
  • (optional) GivenName -> FirstName

This is definitely what ADFS had configured, but it wasn’t working. I finally turned to the previously-mentioned vizportal log and found this: Incoming SAML message has no valid value for email attribute. Please verify ServiceProvider configuration in Identity Provider.

So… Despite what the docs say, Tableau wants an email attribute? In some cases, this is no big deal. Simply edit your Issuance Transform Rules, and add an attribute that maps “E-Mail-Addresses” to the “email” outgoing claim type. Where it gets tricky is when your email address is not the same thing as your username @ your AD domain. Why would this matter? Because, even though Tableau is receiving an attribute called “username,” it tries to extract domain and username from the email address.

Say your email address is When this gets passed to Tableau, Tableau breaks it apart and tries to sign in as\jon.doe. If jon.doe is your username/SAMAccountName and your domain is known internally as, then that’s great. However, if your username is actually jdoe and your internal domain is, this is going to fail with a vizportal error like this:

2017-12-14 10:26:40.253 -0500 (,,,) catalina-exec-4 : INFO com.tableausoftware.domain.user.saml.SAMLExtendedProcessingFilter – Using domain extracted from email in saml response for username
2017-12-14 10:26:40.253 -0500 (,,,) catalina-exec-4 : INFO com.tableausoftware.domain.user.saml.SAMLExtendedProcessingFilter – Using fully qualified username\jon.doe from saml response
2017-12-14 10:26:40.253 -0500 (,,,) catalina-exec-4 : INFO com.tableausoftware.domain.user.saml.SAMLExtendedProcessingFilter – SAML IDP login was successful, proceeding to create session for username :\jon.doe authUserId : Optional.absent() displayName : Optional.absent() email : Optional.of( logoutSupported : true on provided target site Optional.absent()
2017-12-14 10:26:41.563 -0500 (,,,) catalina-exec-4 : ERROR com.tableausoftware.domain.user.saml.SAMLExtendedProcessingFilter – SAML Authentication Failed, please contact the administrator.

Fortunately, you still have a couple easy options. First, if your UserPrincipalName uses your standard domain, rather than something like, you could map that to the “email” attribute. Alternatively, you could just map SAMAccountName to the “email” attribute. If Tableau doesn’t see an “@” symbol in the email, it will simply pass the username along as-is. Problem solved.

I plan to raise this with Tableau support. It could be that I’ve got something wrong or need to update (yes, I do, but I haven’t seen this mentioned as a known issue/bug fix). But, if you need to move past this quickly, perhaps these tips will help. Good luck!


Seeing the Light on a Flat Earth

Some of you may be surprised to hear that there are still people who believe the earth is flat, rather than a sphere. If you search for “flat earth map” or “flat earth disc,” you will see that Earth is actually shaped more like a thick plate than a ball. Now, I am sure this school of thought is made up of at least as many trolls and comedians as there are genuine adherents, but that doesn’t diminish the fun of thinking through the how’s and why’s of a Truman or Matrix world, where reality is not quite what it seems. And sure, there are plenty of articles and YouTube videos debunking various aspects of the theory, but there was one point I was curious to explore on my own: the Sun.

According to Flat Earth Wiki, the sun is 32 miles in diameter and 3,000 miles away from the surface of a flat Earth, as opposed to 432,288 miles across and nearly 93 million miles from a spherical Earth. This same reference, along with many others, reveal that day and night are the result of a spotlight effect, created by the Sun circling around the Equator, shining light on one part of the map in the day and another part at night. The question that came to mind for me, and I have yet to see addressed from either side, is this: “If the Sun were circling above a flat Earth, wouldn’t we be able to see it in the distance even if it were on the other side of the planet?”

Original map image retrieved from

Map of Flat Earth retrieved from (Notations, etc. added by me)

On a sunny day, clouds would not obstruct our view, but perhaps obstacles such as mountains could hide the Sun from us. Well, I set out to discover the answer to my questions, which meant it was time for an experiment. My plan was simple: find a small flashlight, measure its diameter, and setup an area to scale that would represent the distance from Equator to Equator on opposite sides of the Earth. Then, my beautiful assistant (AKA my wife) would suspend the light pointing straight downward over the Equator on one end, and place an observer looking up from the ground on the other. In this case, the observer would be an upside-down iPhone camera to get as close to the ground as I could. Here are the measurements I used:

Property Full size measurements Scaled
Diameter of the Sun 32 miles 2.5 centimeters
Distance to the Sun 3,000 miles 7.689 feet
Diameter of the Equator 12,500 miles 32.039 feet
Highest Point of Mt. Everest 29,035 feet .169 inches

(The radius of the Equator can be found on the Flat Earth Society Wiki. Note that I set the light a little lower and further away, which would theoretically work in the flat Earth theory’s favor.)

And here is a rough diagram of the experiment’s setup:

You will note that there is an obstacle more than twice the height of Mount Everest intentionally blocking the observer. This is because 1.) I wanted to try and view the Sun from the worst possible location, and 2.) I was having trouble finding something that was exactly .169 inches tall to act as Mount Everest. As a side note, it’s really cool to start picturing geographic landmarks on this scale. Anyway, this setup should give us an idea of what we would see if we were standing in the shadow of a giant mountain on the Equator in the middle of the night, looking north across the Earth.

The flashlight used in this experiment

The flashlight used in this experiment

I had a few ideas of what to expect. Maybe the obstacle would block the observer’s view of the Sun. Perhaps the light would be so small and dim at this distance that it would not be visible. Maybe I would at least see the beam of light directing downward from the flashlight. With all these questions rolling around, I turned off the lights in the house, set the iPhone in its location, angled up toward the sky, and snapped a picture. Here is what I saw:

Flashlight Sun

Click to enlarge; it’s a much better view

That pale little circle in the bottom half of the photo? Yeah, that’s the flashlight… Or, the Sun, rather. I don’t know enough about optics and light to explain why the downward-facing spotlight produced a circular image, but I do know the light was facing straight down. I was actually pretty amazed. The photo almost has an outer space beauty to it.

So, what does this tell us? Well, only so much. This wasn’t performed in a controlled environment with unbiased witnesses, and the measurements aren’t perfect. But, I think this demonstrates that the Sun is simply too “high” and large (and not to mention far more intense than this little flashlight), whether you accept a flat Earth or a spherical Earth, not to be seen from one side of the planet to the other if it were simply rotating around a flat surface. I am quite confident you could push that light much further back and even lower and it would still be visible from the opposite side of the Equator. Don’t believe me? Give it a try. I created this calculator with to help scale your setup.

There are of course many other aspects of the flat Earth theory, but plenty of people on both sides of the argument have already gone into great detail on those. This experiment was more about having fun and putting an idea to the test. I’m not really interested in a flat Earth debate, but I am curious to hear ideas for an improved experiment, other more technical explanations of my observations, or your own observations. Have a thought or idea, please share!

A Few iMovie Tricks I Learned on New Year’s Eve

I used to make a lot of stupid videos. Some seemed kind of cool to me at the time, but looking back, I have to disagree with my past self. Most of these were made in iMovie HD. In fact, I preferred iMovie HD so much, I kept porting it from computer to computer (despite ridicule… “iMovie HD? Really?”) until I actually started working with HD video. Kind of ironic that iMovie HD doesn’t really work with HD. Anyway, I decided to make a bit of a time travel spoof this past New Year’s Eve for my friend who is an hour behind (because of geography, not mental capacity) and working with iMovie 10 required me to figure out a few things really quick: how to record in the dark with an iSight (not really an iMovie trick), add titles that don’t fade in or out, and how to get my beloved earthquake effect back.

The finished product

Recording in the dark. This is a simple trick and, again, not really an iMovie issue. In the last few seconds of the video, I needed to record in the dark with only the flashlight highlighting my face. Since I was using the iSight camera with PhotoBooth, it meant a bright screen was right in front of me lighting up the whole space. The solution? Click the record button and then turn the screen brightness all the way down. Simple, right? Yes.

Titles that don’t fade. Another element I wanted to use was some kind of on-screen clock to prove that this all took place shortly after midnight on January 1st, 2017. That should be easy: just add a title with a timestamp. Oh, I see iMovie added a fade to the title, so let me just remove… Hey, there’s no option to remove that fade!

I saw one person’s suggestion of inserting the title into your primary video track, creating a freeze frame from that, and then using the freeze frame without fades as your title. This might work fine if you only need a black background, but I needed the timestamp to sit over top of my video. So, I turned to the Gimp and made a couple PNGs of my timestamp with a transparent background. Dragging these into the movie timeline preserved the transparency and worked as expected. The only thing to note is that you need to turn off the Ken Burns effect, which is automatically applied to imported photos. To do this, select your photo in the timeline, click the crop icon, and choose either “Fit” or “Crop to Fill” to get rid of that effect:

iMovie Photo Cropping

Add an earthquake effect. This element took the most time to figure out. Well, most of my time was spent confirming that iMovie had indeed removed the earthquake effect. While I never found an explicit confirmation, the preponderance of evidence drew me to the conclusion that it is finito. But, I found an unexpected suggestion on Stack Exchange. It’s not the accepted answer, but the user Reem recommends taking small clips of a video and applying the Ken Burns effect (you know, the one we just removed in the previous step).

Inspired by this advice, I split my clip into a few pieces where it needed to be really jerky, applied the Ken Burns effect to each, and dragged the Start and End points around to add variety. This technique actually worked very well when there was a lot of on-screen motion (e.g.: when I very quickly dodged away from the camera and flipped my laptop on its back). However, it has its limitations. I tried adding the same effect over other parts of the video when the camera was relatively still and it was not at all convincing. So, use wisely.

Well, that’s all I have for today. Nothing earth shattering… But a little earth shaking? I was just excited to see it all come together within the very short time table I had to work with.

What are some fun things you’ve come across in iMovie? What are the stupid obvious things I missed that would have made this easier and better?


Michigan’s fall colors dressed each side of the highway as we trekked across the state once more. I thought of my son in the row behind me and how we had made this same trip to the family reunion one year earlier. It had been his first time; the shyness pulling his hood down to conceal his face. I reflected on so many firsts we had witnessed over the past five years: first Christmases, first birthdays, first Easters. We had the joys of seeing them for so many children. But this year, we felt the unfathomable power of something we had never experienced before: seconds.

As foster parents waiting for our forever family, we have been privileged to more numerous firsts than most families enjoy. Yet, so often, the celebrations end there. The happiest Easter is followed by the loneliest. Pages in a scrapbook unfold to reveal the birthday hat your squealing one-year-old wore twelve months ago. It hurts. So all the more of a blessing it has been this year to witness our children’s second birthdays, second Easters, second summer vacations, and soon, their second Christmases with us. It makes us start to believe there will be thirds, fourths, fiftieths, and more.

It feels a morbid thought, but I sometimes wonder who will be at my deathbed. Who might hold my hand to help me across. I pray my children will surround me, even those not with us yet. Seeing them would provide the ultimate confirmation that we made it together. That we stayed a family despite all odds.

Our little drive to the reunion and back was nothing extraordinary. Enjoyable and wonderful as always to come back together and share the joys and sorrows since our last meeting. But, coming home, I was filled with hope that the children in my car could be the ones to carry on this sacred gathering long after the rest of us are gone.

The reunion has passed, the apple crisp well-enjoyed, and we wait to see each other again next October. For now, we turn attention to our children’s second Halloween, the pride rising in us from how wonderful they will look in their second costumes. There is no single word to express all that is inside, but three come close: Thank you, God.

Redirect HTTPS Tableau Traffic to a Valid URL

You’ve heard it before: it’s past time to encrypt ALL the things! Even internal traffic should be encrypted, since you never know what rogue devices or people may be listening on an ethernet port or an unsecured hotspot. That’s why, when I inherited a Tableau server, I decided that encryption should be a priority. Especially when you consider the kind of data that can flow in and out of Tableau. And, Tableau makes it surprisingly easy to turn on TLS (or SSL, as they and so many others like me still call it). What they don’t make so easy is redirecting users over to an address that matches your cert. No big deal if your users have always accessed Tableau Server with the right alias, but until now, we only had an internal address that doesn’t match the cert we applied. The good news is Tableau Server uses Apache for its web server. With a pretty small tweak, you can redirect your users in no time.

Please note: this is not documented or supported by Tableau as far as I can tell. Be sure to test thoroughly before applying to your production environment. I also assume these settings will be overwritten by an update/upgrade, thus needing to be reapplied afterward (update: Having since gone through a few upgrades, I can confirm that these settings need to be reapplied afterward).

As I mentioned, Tableau Server uses Apache for its web server. An interesting choice since Tableau is only supported on Windows. This means a couple rewrite conditions/rules in httpd.conf will have you off and running. The first thing you need to know is where this file lives. It will be under Tableau’s data folder, which is located based on which drive Tableau was installed on. Tableau was installed on C: for us, which puts the httpd.conf file in C:\ProgramData\Tableau\Tableau Server\data\tabsvc\config (we will talk about moving your data folder to another drive in a later post). I am not entirely certain what the structure looks like if you installed on a separate drive, so you may need to do some digging.

Once you have located the httpd.conf file, the second thing you need to know is that this file is formatted for *nix line feeds and carriage returns. I.E: If you open it in Notepad, it will all be jumbled together. If you already have a tool like Notepad++ installed on the server, it should do nicely. In my case, I chose to copy the file to my local machine, edit it with Atom, and then push it back to the server. Just be sure to make a backup of the file first.

Ok, so you’ve found httpd.conf, you’ve made a backup, and opened it up in your favorite *nix-friendly text editor. If you scroll down to around line 581, you will start to see several RewriteCond and RewriteRule lines. Our rules don’t have to go here, but it seemed logical since there are already related rules in the vicinity. If you aren’t familiar with mod_rewrite rules, they basically look for certain conditions in an Apache request and rewrite/redirect (with a 301 by default) the URL sent to the server. Here is what I added after Tableau’s built-in list of rewrite rules:

RewriteCond %{HTTP_HOST} !^tableau\.mycompany\.net [NC]
RewriteCond %{HTTP_HOST} !^localhost [NC]
RewriteRule (.*)$1 [R=301,L]

What does each line mean? The first line looks for requests containing a URL that doesn’t match the address we want people to use. Replace “” with your company’s preferred address for Tableau. Of course, make sure the record actually exists in DNS and points to your Tableau server.

The second line is an AND condition (by virtue of the previous line not ending in “[OR]”) and filters out requests using the “localhost” URL. The reason for this is that Tableau Web Data Connectors (WDC) published on the server will always be refreshed using http://localhost/webdataconnectors/yourWDCname.htm. And, as I found out, Tableau won’t follow the redirect when it tries to extract, but it will seemingly ignore the certificate/server name mismatch. Adding this line makes sure we don’t break any scheduled extracts using a WDC. Side note: it seems that in Tableau 10, you can maintain a list of approved WDC’s external to Tableau (aw yeah!), which I find preferable and would make this line unnecessary.

Now, the third line. This line takes the requests that haven’t been filtered out by the two previous conditions, and rewrites them to use our preferred address. Notice that here I have added the protocol (https://), whereas it is not needed for the conditions since we want to catch HTTP and HTTPS requests. The variables at the end will keep the rest of the URL as-is, so that something like becomes, rather than redirecting to Tableau’s landing page.

Once you have updated httpd.conf with the lines above, restart Tableau Server (tabadmin restart). Now, whenever someone tries the old address, they should be redirected to the new one. This all depends on the visitor or other clients following a 301 redirect, which is pretty standard. Still, be thorough in your testing to account for all conditions.

That’s it! A lot of talking for 3 lines of text.

Get a Working Date/Time Format Using a Tableua Web Data Connector

Here’s a tip that resulted from quite a bit of frustration. It has to do with Tableau’s new-ish Web Data Connector and a difference in JavaScript date functions across browsers (particularly, Chrome and Safari). While trying to pull in JIRA data, depending on which JavaScript method I attempted, I would see either a NULL or NaN (Not a Number) in any date field. The frustrating things is that it worked perfectly in the simulator. I only ran into the problem in Tableau Desktop (on a Mac) and could not find any errors in the logs or console.

To start with, Tableau has a pretty good tutorial to help people get started writing a WDC, which I recommend you check out first if you haven’t already. Within their documentation, you can find a cheat sheet for accepted date/time formats. However, even though I referred to this cheat sheet and tried several formats, I could never get anything to produce a result other than NULL or NaN in Tableau. Again, despite the dates rendering properly using the simulator in Chrome. Writing a WDC wasn’t a high priority, so I would bang my head on it for a while, set it aside for something else, and then come back the next week to do the same thing all over again.

A breakthrough finally came when I asked myself, “Does the simulator behave the same in all browsers?” I fired it up in Firefox and saw the same valid results as I saw in Chrome. Next, I brought up the simulator in Safari. Much to my surprise, the dates produced a NULL or NaN! For my purposes, the WDC was connecting to a proxy server, which then connected to JIRA using PHP’s cUrl functions. In order to confirm my suspicion that Tableau was using Safari, I checked the access log for this proxy server. What user agent did I find when trying to connect using Tableau Desktop, rather than the simulator?


As you can see, Tableau was using Safari. A Google search lead me to this question on Stack Overflow, which made me think Safari was not quite comfortable with the date/time string provided by JIRA (e.g.:2016-07-23T05:31:15.000-0400). The accepted answer suggests trying out moment.js, which I did and found it incredibly easy to use. Just remember to include the moment.js file when you add your WDC to the server.

With moment.js in hand, the solution was simple. I included moment.js in my WDC with something like the following:

<script src="moment.js"></script>

Then, I used the following code to get the date string supplied by JIRA into a format supported by Tableau:

var dateFormat = "Y-MM-DD HH:mm:ss";

var createdDate = moment(issues[ii].fields.created).format(dateFormat);

Tableau magically rendered a real date! So, if you find yourself trying to solve the same puzzle, give moment.js a try and see if that doesn’t get you onto the next hurdle (which is getting Tableau Server to a version that is compatible with the WDC found in the tutorial/simulator).

Compare-ObjectIs: No more weird Foreach… -Contains code

Yesterday, I was again faced with the task of using PowerShell to determine whether one array contained any of the values in another array. Specifically, I had an array of AD group Distinguished Names (DN) and needed to determine if users were members of any of these groups (an LDAP filter would probably be easier, but I was already invested in solving this). Typically, I would handle this with something of a foreach loop: for each user, loop through each of their group memberships and see if the group array contains their group string. This always feels terribly inefficient, so I wanted to find a cleaner way of handling these types of comparisons.

Looking around online, I realized PowerShell has a Compare-Object cmdlet, which sounded promising. It works by accepting a -ReferenceObject and -DifferenceObject, and comparing which values are the same or different between the two. Now, this cmdlet is almost helpful, but really works better for someone interacting with the shell, rather than a script. The output looks something like this:

Screen Shot 2016-05-19 at 7.43.10 AM

The “SideIndicator” tells us which object/array (the reference, or the difference object) has a different value. In this example, the second array contains “orange,” but the first array does not. Conversely, the  first array contains “apple,” but the second does not. Again, handy if you are in the shell, but how do you use this in a script. Well, here is the short of what I came up with:

compare-object $_.MemberOf $includeGroups -includeequal -excludedifferent

You might first notice that there are no “-ReferenceObject” or “-DifferenceObject” parameter names spelled out above. That is because, as with all PowerShell cmdlets, if you specify parameters in the right order, you can skip those names. So, in this case, $_.MemberOf is the reference object and $includeGroups is the difference object. The next two switches are very important for this to work. “-includeequal” tells the cmdlet to return the items that match between the two objects and “-excludedifferent” prevents it from returning the objects that are different. This is because, for this comparison, we really only care about the items that match across arrays.

Continuing the fruit example above, here is what we see:

Screen Shot 2016-05-19 at 7.52.05 AM

This “==” tells us that “pear” and “banana” exist in both arrays. Since we exclude differences, if there are no matches this cmdlet will return $null. That means we can do something like this:

if ( compare-object $MemberOf $includeGroups -includeequal -excludedifferent ) {

  #Do something



... | Where { compare-object $_.MemberOf $includeGroups -includeequal -excludedifferent }

Of course, format it however you would like and surround with parenthesis when using multiple conditions. I feel a little silly that this cmdlet has been there since PowerShell version 3, but I am at least satisfied that I no longer need to employ cumbersome foreach loops in these situations.