Skip to content

Exercise #2_01 | Single Sign On with Flask and Tableau

Genie52 edited this page Jun 14, 2019 · 39 revisions

In most embedding scenarios, you will want to enable single sign-on so that the users that are signed in to your application do not have to also sign in to Tableau Server. There are a few ways to enable single sign-on to Tableau Server.

  • Trusted Authentication: In most scenarios, trusted authentication is the right choice. The exceptions are if you have already deployed one of the below solutions.
  • Active Directory + Kerberos: If all of your users are registered in your Active Directory instance and you already use Kerberos for authentication for other applications, use Active Directory + Kerberos.
  • Active Directory + ‘Enable automatic logon’: If all of your users are registered in your Active Directory instance, but you do not use Kerberos, use Active Directory with the ‘Enable automatic logon’ option (which uses Microsoft SSPI).
  • SAML or OpenID: If you have already use SAML or OpenID in your systems, configure Tableau Server to use your existing SAML or OpenID deployment.

Trusted Authentication

Trusted authentication is, unlike the above options, a piece of functionality specific to Tableau Server. It allows you to trust specific machines to authenticate users on their behalf. Because the authentication happens with simple HTTP requests, it is the most versatile of the single sign-on options and can be used to integrate with, essentially, all other authentication systems.

Below is a summary of the three steps in the trusted authentication workflow:

  1. Configuration: This is a one-time step where you configure Tableau Server to ‘trust’ specific ip addresses, which will then be allowed to authenticate users. The machines to trust are usually the machines running your web application.
  2. POST Request: When the user navigates to a page in your web application that contains Tableau content, the web application will make a server-side POST request to Tableau Server passing in the users’s Tableau Server username, the site the content exists on, and, optionally, the client’s ip address in the form data. If the ip address making the request is trusted, and the user exists in Tableau Server, Tableau Server will return a ticket.
  3. Client loads the view with the ticket: Your web application now instructs the client to load the url of the desired resource, with the ticket inserted. If the ticket is valid, Tableau Server will start a session for the user and the user will see the visualization. Of course, the user does not see the HTTP requests going on behind the scenes, but simply loads a page in your application and sees embedded Tableau content without having to signin.

So what happens if you embedd Tableau vizz inside your portal and do not use SSO? Here is the example!

Now this is really not a good user experience! What we want is a seamless transition - when a user logs in to a portal, opening a new page with Tableau visualization should be seamless like this:

Now lets build this kind of SSO experience with Trusted authentication!

#01 - First lets see this in action. Make sure if you have already running Flask server you stop it with CTRL + C. In command line go to folder 02 - SSO ans start 02-SSO-Finish.py file like this:

python 01-SSO-Finish.py

open http://localhost:5000 and then when portal opens click on the bottom link so we fist experience how it would work without the SSO.

When asked by Tableau - log in as User01 (password: User01).

After you have seen how inconvenient that experience was - go back to http://localhost:5000 and log-in on the front page as **User01 **(hint - portal password can be anything its not actual proper security 😉 😉 )

Then click on the link for the amazing SSO experience!

Stop the Flask server with CRTL + C and lets see the code!

#02 - You are going to edit two files - main python file and one of the HTML files. Layout of the files is as follows (I have remove FINISH and START from the names for more clarity):

Open and review 01-SSO-Finish.py in Atom (or open this link to code in another tab). You will find comments in code that will help you understand it better.

File open in Atom editor:

#03 - Now open 01-SSO-Start.py in Atom and we will add code in three places:

First edit - under:

# --------- 01-PASTE START - FORM variable placeholders ------------

write or copy/paste the part of the code that defines the form fields and labels we are going to pass from python file to index-tableau-Start.html file:

class UserForm(FlaskForm):   
    username = StringField("Username:")
    password = StringField("Password:")
    submitForm = SubmitField("Login!")

Second edit - under:

# --------- 02-PASTE START - FORM data management ------------

write or copy/paste the code that will read the username field in the HTML form and send that username to Tableau server as a parameter in http://localhost/trusted URL. This will return us (hopefully) a valid trusted ticket. Cautionary tip - python is very sensitive on indention, so make sure this code is properly positioned (check finished file 01-SSO-Finish.py if you are not sure..)

   if form.validate_on_submit():        
        username = form.username.data
        form.username.data = ''
        global tableau_ticket_return
        tableau_ticket_return = requests.post("http://localhost/trusted?username=" + username)

Third edit - under:

# ----- 03-PASTE START - passing the USERNAME and TICKET to another HTML page -----

write or copy/paste the code that sends tableau ticket and username as variables to loginTableauPage.html where we use this info to load the Tableau visualization in a seamless SSO manner.

@app.route('/loginTableauPage')
def loginTableauPage():
return render_template('loginTableauPage.html', tableau_ticket = tableau_ticket_return.text, username = username)

So now we should have complete python edited start file - it should look same as our finish file - 01-SSO-Finish.py.

#04 - Now we need to edit start HTML file where we use a form to input username and password. But first lets review the finished file - open file index-tableau-Finish.html from templates folder (/02-SS0/templates/) in your Atom editor and review it. Form code is of particular interest to us:

<form method="POST">
    {{form.hidden_tag()}}
    <table style="width:300px;border: 1px solid black;" align="middle">
     <tr>
       <td>{{form.username.label}}{{form.username()}}</td><td></td>
     </tr>
     <tr>
       <td>{{form.password.label}} {{form.password()}}</td><td></td>
     </tr>
     <tr>
       <td align="middle">{{form.submitForm()}}</td>
     </tr>
    </table>
</form>

This code above ties to the form definition in 01-SSO-Finish.py found below:

class UserForm(FlaskForm):
    # Below are the form fields we want to be able to capture and send to Tableau server.
    # These are used as form attributes in .html file
    # in the quotes is the text user will see when using the form
    username = StringField("Username:")
    password = StringField("Password:")
    submitForm = SubmitField("Login!")
    
    # below are just bites of code to make a point...
    if form.validate_on_submit():
    # get the username from the form! 
        username = form.username.data
        tableau_ticket_return = requests.post("http://localhost/trusted?username=" + username)

# send the ticket to html page that will show Tableau viz!
@app.route('/loginTableauPage')
def loginTableauPage():
return render_template('loginTableauPage.html', tableau_ticket = tableau_ticket_return.text, username = username)

A little bit more of visual clarification how it all ties in can be found in the picture below - (same applies for password field and submit button!):

When we fill out the form and press the submit button - username and password information will be passed to python file and we can use it to obtain trusted ticket from Tableau Server.

Finally lets edit the HTML code! - open index-tableau-Start.html from templates folder (/02-SS0/templates/) in your Atom editor and below:

<!-- PASTE CODE - START HERE!!! -->

write or copy/paste the following code (I trust you now know what is this code doing :-) ):

<form method="POST">
 {{form.hidden_tag()}}
 <table style="width:300px;border: 1px solid black;" align="middle">
   <tr>
    <td>{{form.username.label}}</td><td>{{form.username()}}</td>
   </tr>
   <tr>
     <td>{{form.password.label}}</td><td>{{form.password()}}</td>
   </tr>
   <tr>
     <td align="middle">{{form.submitForm()}}</td>
   </tr>
 </table>
</form>

Don't forget to save the file and start 01-SSO-Start.py from CMD:

python 01-SSO-Start.py

Open browser and go to http://localhost:5000, enter username and the password then login and see if your SSO experience works well!