SSO Authentication
How to implement SSO authentication with Azure as the provider, including token retrieval and refresh.
Nomad Media has built-in SSO capability. The following examples use JavaScript and Python with Azure as the SSO provider.
CLIENT_DOMAIN — Your domain ID provided during environment setup.
SSO_AUTH_PROVIDER — The constant value is
"azure". This is the SSO provider name, must be consistent, and appears in both the URL and token names.
Login
// Build the SSO provider URL
const authProviderLoginUrl = `${adminApiUrl}/auth/${constants.SSO_AUTH_PROVIDER}/login`;
// Navigate to the provider URL
location.href = authProviderLoginUrl;
// When it returns, get query string parameters
const urlParams = new URLSearchParams(window.location.search);
const authCallbackFromQueryString = urlParams.get("authCallback");
// Check for valid authCallback
if (authCallbackFromQueryString) {
// Get both tokens from the query string
const token = urlParams.get(`${constants.SSO_AUTH_PROVIDER}_token`);
const refreshToken = urlParams.get(`${constants.SSO_AUTH_PROVIDER}_refresh_token`);
// Store both tokens
sessionStorage.setItem("token", token);
sessionStorage.setItem("refreshToken", refreshToken);
}import urllib.parse
import os
login_url = adminApiUrl + "/auth/" + constants.SSO_AUTH_PROVIDER + "/login"
auth_callback_from_query_string = None
# Redirect to login URL
os.system("start " + login_url)
# Get authCallback from query string
url_params = urllib.parse.parse_qs(urllib.parse.urlparse(window.location).query)
if "authCallback" in url_params:
auth_callback_from_query_string = url_params["authCallback"][0]
if auth_callback_from_query_string:
token = url_params.get(constants.SSO_AUTH_PROVIDER + "_token")
refresh_token = url_params.get(constants.SSO_AUTH_PROVIDER + "_refresh_token")
# Store both tokens
sessionStorage["token"] = token
sessionStorage["refreshToken"] = refresh_tokenRefreshing Tokens
The token is valid for the number of seconds returned in the login response (default: 1 hour). After expiry, all API calls return 401 Not Authorized. Use the refreshToken from the initial login to request a new token without re-authenticating.
Endpoint:
POST https://admin-app.${CLIENT_DOMAIN}/api/auth/${SSO_AUTH_PROVIDER}/renew
// headers
Content-Type: application/json
// body
{
"refreshToken": "<refresh_token>"
}export default async function refreshToken() {
const refreshToken = sessionStorage.getItem("refreshToken");
if (!refreshToken) {
throw new Error("Refresh Token: The refresh token is invalid");
}
const headers = new Headers();
headers.append("Content-Type", "application/json");
const body = { refreshToken: refreshToken };
const refreshTokenUrl = `https://{adminApiUrl}/api/auth/${constants.SSO_AUTH_PROVIDER}/renew`;
const response = await fetch(refreshTokenUrl, {
method: "POST",
headers: headers,
body: JSON.stringify(body)
});
if (response && response.ok) {
const refreshTokenResponse = await response.json();
sessionStorage.setItem("token", refreshTokenResponse.token);
sessionStorage.setItem("refreshToken", refreshTokenResponse.refreshToken);
return;
}
}import json, requests
def refreshToken(REFRESH_TOKEN: str) -> dict:
if (not REFRESH_TOKEN):
raise Exception("Refresh Token: The refresh token is invalid")
API_URL = "https://{adminApiUrl}/api/auth/{SSO_AUTH_PROVIDER}/renew"
HEADERS = {
"Content-Type": "application/json"
}
BODY = {
"refreshToken": REFRESH_TOKEN
}
try:
RESPONSE = requests.post(API_URL, headers=HEADERS, data=json.dumps(BODY))
INFO = json.loads(RESPONSE.text)
if RESPONSE.status_code != 200:
raise Exception("Response returned " + str(RESPONSE.status_code))
return INFO
except:
raise Exception("Refresh Token failed: " + json.dumps(RESPONSE.text))The new token returned should replace the previous token for all subsequent API calls. The refreshToken can be reused repeatedly to continue obtaining new tokens.
