Python API/Rest API and authentication with SSO enabled

Both our APIs—Python and REST—allow the use of a username/password pair for authentication when connecting to Shotgun, but if a site is using SSO, the username/password method is not allowed.

While this may be surprising, there is a good explanation:

Shotgun is no longer the gate-keeper, and cannot tell by itself if your credentials are valid. This task is now handled by your IdP (Identity Provider, like Azure, Okta, etc.).

(Note: scripts that authenticate with a script_name/api_key pair are not impacted by the use of SSO, it is business-as-usual for them)

When using a browser, Shotgun redirects you to your IdP (using a 302) and then the IdP redirects your browser back to Shotgun once authenticated. Unfortunately, this mechanism is not possible when using a API-based communication. The handshake process between the servers involves Javascript being interpreted and the actual login flow varies across IdPs.

But, can't Shotgun just contact the IdP to validate the credentials?

Unfortunately, no. Depending on your specific network topology, Shotgun may not able to directly connect to your IdP (in fact, our SSO implementation assumes that Shotgun cannot connect directly to an IdP). As well, no IdP offers an API to validate a password as it is a potential security risk.

The key take-away is:

Use of username/password in API calls are inherently insecure and highly discouraged.

So, what are my options to authenticate with the API when SSO is enabled?

Use a web browser—or a browser-like widget—to authenticate and then use the session_id from the browser to initiate an API connection with Shotgun. This is what is done by Shotgun Create, Shotgun Desktop, and RV.

These applications use a special path on the Shotgun server (<SERVER_URL>/auth/renew) to start an authentication process for a user. Once the web widget gets back to the <SERVER_URL>/auth/landing, we know that the login process was successful. The widget is then closed and we fetch the _session_id value from the cookie jar. This is used to create an API connection to Shotgun.

It is assumed that any web page shown to the user is part of the authentication process or is reporting back errors to the users with additional instructions. If the widget is closed without reaching the landing page, then we know the user abandoned the process.

The mechanism used by our applications is available to all external clients, but the simplest way to make use of it is to use Shotgun Toolkit in combination with Shotgun Desktop or Shotgun Create installed on your system to use the existing session.

Additional Background and Context

Shotgun's SSO implementation relies on SAML2.0 as this older standard maximizes the number of IdP we can support. This means we do not have to rely on IdP-specific SDKs or APIs—thereby reducing maintenance and support complexity.

We expect Shotgun and the IdP to know about each other, but we do not rely on direct communications between the two. In order to support the case where Shotgun is hosted on the cloud, but the IdP is hosted internally in the company’s infrastructure. For Shotgun to connect to the IdP, a special firewall configuration would be needed to allow.

Instead, we rely on the client application (e.g.—the browser or the web widget) to be the relay for communications between the two servers. The expectation being that the user’s machine is able to reach both Shotgun and the IdP. This also sheds some light on the absence of server-to-server calls to validate the user’s credentials.

Implementation Examples

Here are two potential examples of ways to proceed that connects to a site and gets the list of projects (before.py) using a username and password when assuming a simple initial Python API script:

Sample 1—Using Toolkit for User Authentication Reference

(after_simple.py) We use the toolkit to get a reference to the currently authenticated user and create a new connection to the server (which is the equivalent of a Shotgun() object creating in the Python API). If there are no currenlty authenticated users, we instruct the script invoker to start either the Shotgun Desktop or Shotgun Create and authenticate.

Sample 2—Using Current Toolkit User

(after_self_auth.py) We attempt to use the current toolkit user. If there are none, we create a Qt Application (so that the GUI can be shown, not just command-line prompts), and then ask the user to select a site and authenticate.

These are just simple examples that can easily be modified and tailored to suit the different needs.

They each have pros and cons, and your individual use case will dictate which one makes more sense for you.

-Patrick

3 Likes

Finally, here’s an overview of pros & cons of using Toolkit as opposed the the Python API:

Under the hood, the Toolkit uses the Python API, but a lot of scaffolding and abstraction is built on top of it.

1. Using the Python SDK with username/password

Pro:
-You can have multiple scripts connecting to different sites with different users at the same time

Con:
-SSO is not supported

2. the simple integration with the Toolkit

Pros:
-Support all current and future authentication mode, as well as handle MFA and other security mechanisms
-The changes to an existing script is minimal (import sgtk, create connection). The rest of the Python API script stays the same

Cons:
-Can only be connected to the same site as the current Toolkit session
-You need to query which user and site are in play, to get the current context of the connection
-Dependent on another application to initiate the connection (SG Desktop or Create), You do not control the site/user

3. the self-auth integration with the toolkit (as is show in the sample code):

Pros:
-Support all current and future authentication mode, as well as handle MFA and other security mechanisms
-The changes to an existing script is minimal (import sgtk, create connection). The rest of the Python API script stays the same
-No need to defer to the SG Desktop or Create to initiate the authentication

Cons:
-Can only be connected to the same site as the current Toolkit session
-You need to query which user and site are in play, to get the current context of the connection
-You need to have PySide/PySide2 available on your machine (which is not that big of a deal if you rely on an existing SG Desktop install)
-Since a GUI is shown to the user to select the site/user, no control over those values
-Loading PySide and creating a QApplication does induce increased startup times

2 Likes