Authentication to SAS Viya: a couple of approaches

Need to authenticate on REST API calls

In my blog series regarding SAS REST APIs (you can read all of my posts on this topic here) I outlined how to integrate SAS analytical capabilities into applications. I detailed how to construct REST calls, build body parameters and interpret the responses. I've not yet covered authentication for the operations, purposefully putting the cart before the horse. If you're not authenticated, you can't do much, so this post will help to get the horse and cart in the right order.

While researching authentication I ran into a couple of resources on SAS and OAuth. First, what I consider the gold standard in Mike Roda’s SAS Global Forum paper OpenID Connect Opens the Door to SAS Viya APIs. We have also re-written the SAS Viya REST API ‘Getting Started’ documentation on developer.sas.com, which covers details on application registration and access token generation. The rewrite includes sample code for both curl and Python.

Consider this post a quick guide to summarize these resources and shed light on authenticating via authorization code and passwords.

What OAuth grant type should I use?

Choosing the grant method to get an access token with OAuth depends entirely on your application. You can start with this guide Which OAuth 2.0 grant should I implement? to understand the basics of OAuth grant type options. For a SAS perspective, refer to Tara St. Clair’s article Building custom apps on top of SAS Viya, Part Three: Choosing an OAuth flow.

This post covers three grant methods: authorization code, client credentials, and password. Authorization code grants are generally used with web applications and considered the safest choice. The client credentials grant is not associated with any user and is scoped according to the authorities registered to the client. Password grants are most often used by mobile apps and applied in trusted environments. The password grant type is not considered secure and should not be used in production environments.

Please note that as of SAS Viya 2023.1, use of the Consul token is no longer required to register clients. Users in the SAS Administrators group can now generate the access token for client registration. I'll discuss both methods below in separate sections. Be sure to check your SAS Viya version and navigate to the appropriate instructions. (Click here to skip to the section for SAS Viya 2022.x and prior)

SAS Viya 2023.1 and Later

The process, briefly

Getting an external application connected to the SAS Viya platform requires a series of steps. The process below pertain to the authorization code grant type; however, the steps are similar for all grant types.

User in the SAS Administrators group generates access token to register a new Client ID

Use the access token to register the new client ID and secret

Obtain the authorization code

Acquire the OAuth access token of the Client ID using the authorization code

Call the SAS Viya API using the access token for the authentication.

The process requires multiple roles. A SAS administrator performs steps 1 and 2. A script or app provides the URL to an end user for step 3. This produces an authorization code and the user plugs it back into the script or application, so it can continue.

Registering the client and getting the authorization code (steps 1, 2, and 3) are one-time processes. The access and refresh tokens (step 4) are created once and only need to be refreshed if/when the token expires. Once you have the access token, you can call any API (step 5) if your access token is valid.

The process, in detail

Let's look at each grant type in more detail.

Get an access token using an authorization code

For all three grant types covered, you must register the client. The process explained here is in the context of the the authorization code grant type. The client registration process is the same across all grant types, except for the authorization_code parameter. It must match the grant type procedure followed by the user later on.

Step 1: SAS Administrator generates an access token to register a new client

Using admin password

A user in the SAS Administrators group makes and API call to SAS Logon to generate an access token, which will in turn be used to register a client (application). Below is an example of the command where the resulting token is stored in the BEARER_TOKEN variable.

export BEARER_TOKEN=`curl -sk -X POST \
"https://sasserver.demo.sas.com/SASLogon/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d 'clientid=sas.cli&grant_type=password&username=user&password=password' | awk -F: '{print $2}'|awk -F\" '{print $2}'`

Using a browser and credentials

Place the following URL in a browser.

https://sasserver.demo.sas.com/SASLogon/oauth/authorize?client_id=sas.cli&response_type=token

If presented with the SAS login screen, log in with your credentials. Once logged in, notice the very long URL in the address bar. It should have a form similar to the following.

https://sasserver.demo.sas.com/SASLogon/out_of_band#token_type=bearer&access_token=eyJhbGciOiJSUzI.....5ag2sumb9A&expires_in=3599&scope=.....

This string contains, among other things an access token. Paste the URL to an editor and then copy the contents between access_token= and &expires (that's the access_token).

Now let's put the access token into a variable with the following command.

export BEARER_TOKEN=eyJhbGciOiJSUzI.....5ag2sumb9A

Next, we'll use the value of BEARER_TOKEN to register the client.

Step 2: Register the new client

Change the client_id and the client_secret in the code below. For detailed guidance on creating and managing Client IDs and Secrets, refer to this page. Scopes should always include "openid" along with any other uaa definitions this client needs to get in the access tokens. Check with your SAS administrator for which scopes to include. You can find more information on scopes and authorities (related parameter for client credentials grant) in this SAS Communities thread.

$ curl -k -X POST "https://sasserver.demo.sas.com/SASLogon/oauth/clients" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BEARER_TOKEN" \
-d '{
"client_id": "myclientid",
"client_secret": "myclientsecret",
"scope": ["openid","uaa.user"],
"authorized_grant_types": ["authorization_code","refresh_token"],
"authorities": ["<sas custom user groups as needed>"],
"redirect_uri": "urn:ietf:wg:oauth:2.0:oob",
"autoapprove":true
}'

And the response:

{
"scope":[
"openid"
"uaa.user"],
"client_id":"myclientid",
"resource_ids":[
"none"],
"authorized_grant_types":[
"refresh_token",
"authorization_code"],
"redirect_uri":[
"urn:ietf:wg:oauth:2.0:oob"],
"autoapprove":[
"true" ],
"authorities":[
"uaa.none"],
"lastModified":1547138692523,
"required_user_groups":[]
}

Step 3: Get authorization code

Place the following URL in a browser. Change the hostname and myclientid in the URL as needed.

https://sasserver.demo.sas.com/SASLogon/oauth/authorize?client_id=myclientid&response_type=code

The browser redirects to the SAS login screen. Log in with your SAS user credentials.

SAS Logon Screen

After submitting your credentials, you'll see an authorization code displays on the screen and in the URL. You will use this code in Step 4 below.

Authorization Code displays on the screen

And at the end of the resulting URL

Steps 1-3 for SAS Viya 2022.12 and Prior

Expand to view detailed steps

The process, briefly

Getting an external application connected to the SAS Viya platform requires a series of steps. The process below pertain to the authorization code grant type; however, the steps are similar for all grant types.

Use the SAS Viya configuration server's Consul token to obtain an access token to register a new Client ID

Use the access token to register the new client ID and secret

Obtain the authorization code

Acquire the OAuth access token of the Client ID using the authorization code

Call the SAS Viya API using the access token for the authentication.

The process requires multiple roles. A SAS administrator performs steps 1 and 2. A script or app provides the URL to an end user for step 3. This produces an authorization code and the user plugs it back into the script or application, so it can continue.

Registering the client and getting the authorization code (steps 1, 2, and 3) are one-time processes. The access and refresh tokens (step 4) are created once and only need to be refreshed if/when the token expires. Once you have the access token, you can call any API (step 5) if your access token is valid.

The process, in detail

Let's look at each grant type in more detail.

Get an access token using an authorization code

For all three grant types covered, you must register the client. The process explained here is in the context of the the authorization code grant type. The client registration process is the same across all grant types, except for the authorization_code parameter. It must match the grant type procedure followed by the user later on.

Step 1: Get the SAS Viya Consul token to register a new client

The first step to register the client is to get the consul token from the SAS server. As a SAS administrator (sudo user), access the consul token using the following commands:

For SAS Viya 2020.1 and later

On the SAS Viya cluster, run the following command to get the Consul token (replace value to fit your environment):

kubectl -n sse get secret sas-consul-client -o jsonpath="{.data.CONSUL_TOKEN}" | echo "$(base64 -d)"

And the response: 64e01b03-7dab-41be-a104-2231f99d7dd8

For SAS Viya 3.5 and before

On the SAS Viya server, run the following command to get the Consul token and add it to the CONSUL_TOKEN environment variable:

$ export CONSUL_TOKEN=`cat /opt/sas/viya/config/etc/SASSecurityCertificateFramework/tokens/consul/default/client.token`

And the response: 64e01b03-7dab-41be-a104-2231f99d7dd8 (when not stored in a variable).

The Consul token returns and is used to obtain an access token used to register the new application. Use the following cURL command to get the token:

$ curl -k -X POST "https://sasserver.demo.sas.com/SASLogon/oauth/clients/consul?callback=false&serviceId=myclientid" \
-H "X-Consul-Token: $CONSUL_TOKEN"

And the response:

{
"access_token":"eyJhbGciOiJSUzI1NiIsIm...",
"token_type":"bearer",
"expires_in":35999,
"scope":"uaa.admin",
"jti":"de81c7f3cca645ac807f18dc0d186331"
}

Where serviceid in the URL represents the name of the client to register ('myclientid' in this case). The returned token can be lengthy. To assist in later use, create an environment variable from the returned token:

$ export BEARER_TOKEN="eyJhbGciOiJSUzI1NiIsIm..."

Step 2: Register the new client

Change the client_id, client_secret, and scopes in the code below. For detailed guidance on creating and managing Client IDs and Secrets, refer to this page. Scopes should always include "openid" along with any other groups this client needs to get in the access tokens. You can specify "*" but then the user gets prompted for all available groups. The example below just uses one additional group named "group1". Check with your SAS administrator for which scopes to include. You can find more information on scopes and authorities (related parameter for client credentials grant) in this SAS Communities thread.

$ curl -k -X POST "https://sasserver.demo.sas.com/SASLogon/oauth/clients" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $BEARER_TOKEN" \
-d '{
"client_id": "myclientid",
"client_secret": "myclientsecret",
"scope": ["openid", "group1"],
"authorized_grant_types": ["authorization_code","refresh_token"],
"redirect_uri": "urn:ietf:wg:oauth:2.0:oob",
"autoapprove":true
}'

And the response:

{
"scope":[
"openid",
"group1"],
"client_id":"myclientid",
"resource_ids":[
"none"],
"authorized_grant_types":[
"refresh_token",
"authorization_code"],
"redirect_uri":[
"urn:ietf:wg:oauth:2.0:oob"],
"autoapprove":[
"true" ],
"authorities":[
"uaa.none"],
"lastModified":1547138692523,
"required_user_groups":[]
}

Step 3: Approve access to get authentication code

Place the following URL in a browser. Change the hostname and myclientid in the URL as needed.

https://sasserver.demo.sas.com/SASLogon/oauth/authorize?client_id=myclientid&response_type=code

The browser redirects to the SAS login screen. Log in with your SAS user credentials.

SAS Login Screen

On the Authorize Access screen, select the openid checkbox (and any other required groups) and click the Authorize Access button.

Authorize Access form

After submitting the form, you'll see an authorization code. For example, "lB1sxkaCfg". You will use this code in the next step.

Authorization Code displays

From here on, the process of generating the access token is the same, regardless of SAS Viya release. Please proceed to Step 4.

Step 4: Get an access token using the authorization code

Now we have the authorization code and we'll use it in the following cURL command to get the access token to SAS.

$ curl -k https://sasserver.demo.sas.com/SASLogon/oauth/token \
-H "Accept: application/json" -H "Content-Type: application/x-www-form-urlencoded" \
-u "myclientid:myclientsecret" -d "grant_type=authorization_code&code=YZuKQUg10Z"

And the response:

{
"access_token":"eyJhbGciOiJSUzI1NiIsImtpZ...",
"token_type":"bearer",
"refresh_token":"eyJhbGciOiJSUzI1NiIsImtpZC...",
"expires_in":35999,
"scope":"openid",
"jti":"b35f26197fa849b6a1856eea1c722933"
}

We use the returned token to authenticate and authorize the calls made between the client and SAS. We also get a refresh token we use to issue a new token when the current one expires. This way we can avoid repeating all the previous steps. I explain the refresh process further down.

We will again create environment variables for the tokens.

$ export ACCESS_TOKEN="eyJhbGciOiJSUzI1NiIsImtpZCI6ImxlZ..."
$ export REFRESH_TOKEN="eyJhbGciOiJSUzI1NiIsImtpZC..."

Step 5: Use the access token to call SAS Viya APIs

The prep work is complete. We can now send requests to SAS Viya and get some work done. Below is an example REST call that returns the top level folders.

$ curl -k https://sasserver.demo.sas.com/folders/folders?filter=isNull(parent) \
-H "Authorization: Bearer $ACCESS_TOKEN"

And the (partial) response:

{
"links": [
{
"method": "GET",
"rel": "collection",
"href": "/folders/folders",
"uri": "/folders/folders",
"type": "application/vnd.sas.collection"
},
{
"method": "GET",
"rel": "self",
"href": "/folders/folders?start=0&limit=20",
"uri": "/folders/folders?start=0&limit=20",
"type": "application/vnd.sas.collection"
},
{
"method": "POST",
"rel": "createFolder",
"href": "/folders/folders",
...

Use the refresh token to get a new access token

To use the refresh token to get a new access token, simply send a cURL command like the following:

$ curl -k https://sasserver.demo.sas.com/SASLogon/oauth/token -H "Accept: application/json" \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "myclientid:myclientsecret" \
-d "grant_type=refresh_token&refresh_token=$REFRESH_TOKEN"

And the response:

{
"access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6ImxlZ...",
"token_type":"bearer",
"refresh_token":"eyJhbGciOiJSUzI1NiIsImtpZCSjYxrrNRCF7h0oLhd0Y",
"expires_in":35999,
"scope":"openid",
"jti":"a5c4456b5beb4493918c389cd5186f02"
}

Note the access token is new, and the refresh token remains static. Use the new refresh token for future REST calls. Make sure to replace the ACCESS_TOKEN variable with the new token. Also, the access token has a default life of ten hours before it expires. Most applications deal with expiring and refreshing tokens programmatically. If you wish to change the default expiry of an access token in SAS, make a configuration change in the JWT properties in SAS.

Get an access token using the client credentials grant

The steps to obtain an access token using the client credentials grant are similar to the authorization code. I highlight the differences below, without repeating all the steps. The process for registering the client is the same as described earlier, except for the grant type parameter where you will now use "authorized_grant_types": ["client_credentials"]. With client credentials, there is no concept of a refresh token, so it's been removed from the parameter.

Now that the client is registered, the only thing left is to get the access token. Use the code below to get the token:

curl -k -X POST "https:///SASLogon/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-u "myclientid:myclientsecret"

That's it. You can now use the access token retuned in the preceeding call to make REST API calls.

Get an access token using the password grant

The steps to obtain an access token using the password grant are again similar to those describe earlier. When registering the client, use the password grant "authorized_grant_types": ["password","refresh_token"].

The client is now registered on the SAS Viya server. To get the access token, we send a command like we did when using the authorization code and client credentials, just using the username and password.

curl -k https://sasserver.demo.sas.com/SASLogon/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded"
-u "myclientid:myclientsecret"
-d "grant_type=password&username=sasdemo&password=mypassword"

And the response:

{
"access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6Imx...",
"token_type":"bearer",
"refresh_token":"eyJhbGciOiJSUzI1NiIsImtpZ...",
"expires_in":43199,
"scope":"DataBuilders ApplicationAdministrators SASScoreUsers clients.read clients.secret uaa.resource openid PlanningAdministrators uaa.admin clients.admin EsriUsers scim.read SASAdministrators PlanningUsers clients.write scim.write",
"jti":"073bdcbc6dc94384bcf9b47dc8b7e479"
}

From here, sending requests and refreshing the token steps are identical to the method explained in the other code examples.

Final thoughts

At first, OAuth seems a little intimidating; however, after registering the client and creating the access and refresh tokens, the application will handle all authentication components . This process runs smoothly if you plan and make decisions up front. I hope this guide clears up any question you may have on securing your application with SAS. Please leave questions or comments below.

Authentication to SAS Viya: a couple of approaches was published on SAS Users.