Throughout the last year leading up to the SAS Viya Stable 2022.10 release the default token lifetimes for SAS Viya have been changing. With the SAS Viya 2022.10 Stable release the Access Token now has a default lifetime of 1 hour while the Refresh Token has a default lifetime of 90 days. It should be noted that the current SAS Viya 2022.09 LTS release still has a default lifetime for the Access Token of 4 hours, while the Refresh Token lifetime is 90 days. Refresh Tokens, as we will explore, are revokable so they can be long lived. Whereas the Access Tokens are not revokable and so they have a much shorter lifetime.
Given these lifetime values for the tokens I wanted to discuss some implications for the SAS Viya CLI, how tokens can be revoked and the implications for any custom clients of SAS Logon Manager. Previously, Edoardo Riva has discussed Tuning the authentication timeout for long-running jobs where he discusses the implications for situations where clients have long-running sessions that try to use expired Access Tokens – and obviously fail.
As we have stated above there are two types of tokens generated by SAS Logon Manager. The Access Token is used to access the different SAS Viya services and the Refresh Token, if requested, can be used to obtain a new Access Token. Most of the time when using the SAS Viya web applications, you will not need to be concerned about the SAS Logon Manager generated tokens. Since the tokens are requested and used seamlessly by the various SAS Viya web applications. The tokens are never exposed to the end-user’s browser and the end-user never has direct access to their tokens.
However, there are other cases where the end-user does have access to their tokens. This could be when leveraging the supported third-party programming languages such as Java, Python, or Lua to interact with either SAS Cloud Analytic Services REST API or other SAS Viya REST APIs. Or when using the SAS Viya CLI. The SAS Viya CLI will place the Access Token and Refresh Token in a credentials.json file within the user’s home directory. On Linux this would be ~/.sas/credentials.json and for example would contain:
{
"Default": {
"access-token": "eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vbG9jYWxob3N0L1NBU0xvZ29uL3Rva2VuX2tleXMiLCJraWQiOiJsZWdhY3ktdG9rZW4ta2V5IiwidHlwIjoiSldUIn0.
eyJqdGkiOiI1MzI1Yzk5YTAyZTM0NGNhOTNlZWExMTJjODAzYWJhNyIsInN1YiI6IjIyMGIyODI5LTQ4M2UtNDQ3My1hZWEwLWJiMDc2Nzk2YWUyYiIsInNjb3BlIjpbImNsaWVudHMucmVhZCIsImNsa
WVudHMuc2VjcmV0IiwidWFhLnJlc291cmNlIiwib3BlbmlkIiwidWFhLmFkbWluIiwiY2xpZW50cy5hZG1pbiIsInNjaW0ucmVhZCIsInVhYS51c2VyIiwiU0FTQWRtaW5pc3RyYXRvcnMiLCJjbGllbn
RzLndyaXRlIiwic2NpbS53cml0ZSJdLCJjbGllbnRfaWQiOiJzYXMuY2xpIiwiY2lkIjoic2FzLmNsaSIsImF6cCI6InNhcy5jbGkiLCJncmFudF90eXBlIjoicGFzc3dvcmQiLCJ1c2VyX2lkIjoiMjI
wYjI4MjktNDgzZS00NDczLWFlYTAtYmIwNzY3OTZhZTJiIiwib3JpZ2luIjoidWFhIiwidXNlcl9uYW1lIjoic2FzYm9vdCIsImVtYWlsIjoibm9uZSIsImF1dGhfdGltZSI6MTY2OTY0MzAwMSwicmV2
X3NpZyI6IjU1MGI0ZTUyIiwiaWF0IjoxNjY5NjQzMDAxLCJleHAiOjE2Njk2NDY2MDEsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3QvU0FTTG9nb24vb2F1dGgvdG9rZW4iLCJ6aWQiOiJ1YWEiLCJhdWQiO
lsic2NpbSIsImNsaWVudHMiLCJzYXMuKiIsInVhYSIsIm9wZW5pZCIsInNhcy5jbGkiXX0.PcGyJQEG1maldQtwQ3FiCKZWZ_SIGckvF8X24XppVRUWktpmMmxQGdD-lZzPPJ0D9HJ51kyzkKETseFueo
CSjgxdwvLi4TiNEgIAgln-itcmtRmRzdFLKtWufgcZLuU-Fx9aH5YwVJIAgcJWDRUcIR_dwBMC2AJQOqWKF15JoPi07gmTjLejQcIf23OiM4jX0RZWJjKeXFHNvvJ67EqmO90oUbhmyhQ-l-hagh-UqFk
kueOFZUkbLy6PGrcGMWLgARJ6oTkXCRMide61j7hXk2lR5X-caxhZ6hdlctGR39uEY8gBQZhPMOE6j-vtEQrSXf-hjmX1Y1Uy6w3jO_bxHQ",
"expiry": "2022-11-28T14:43:20Z",
"refresh-token": "642db5db07e140bbb19262793b0f3c06-r"
}
In this output you can see that authenticating with the SAS Viya CLI has obtained the Access Token and Refresh Token. The Access Token is a signed JSON Web Token while, in this case, the Refresh Token is an opaque token. With the SAS Viya 2022.09 Stable release the SAS Viya CLI started to use opaque tokens for the Refresh Token. Also note the "-r" at the end of the Refresh Token, this means that the Refresh Token can be revoked. Specifically, when you issue the command sas-viya auth logout the SAS Viya CLI will revoke the existing Refresh Token and remove the contents of the credentials.json file. This way even if someone has managed to obtain a copy of the Refresh Token it cannot be abused once the logout command is issued.
The same information can be viewed in a nicer format using the SAS Viya CLI itself. The command sas-viya profile show will display essentially the same information, as shown here:
Current settings for the [Default] profile:
Setting Current Value
output text
sas-endpoint https://sasviya.customer.com
access-token eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vbG9jYWxob3N0L1NBU0xv...
expiry 2022-11-29T12:36:41Z
refresh-token 6c51cf4fa54d4a76b3c118f3c5350ec5-r
ansi-colors-enabled true
oauth-client-id sas.cli
It should be noted that in both cases the expiry time is shown in the UTC time zone, which might not reflect the same time zone as the host where you are running the SAS Viya CLI.
The SAS Viya CLI will automatically use the opaque Refresh Token to obtain a new Access Token. This means that even when the Access Token has expired you are still able to run SAS Viya CLI commands, so long as the Refresh Token has not expired, and you have not logged out. This does not require any interaction from the end-user. So, with the SAS Viya 2022.09 LTS release after 4 hours the Access Token will be automatically refreshed for you. While with SAS Viya 2022.10 Stable release (and later) this occurs after 1 hour. If you look at the credentials.json file, you will see that the Access Token has been refreshed and the expiry time moved forward. If you attempt to use the SAS Viya CLI after the Refresh Token has expired, you’ll be presented with the following message:
The following errors have occurred:
The user token is expired. Login again before attempting any commands.
Http Status: 0
This means that if you have a secured environment where you want to run scheduled tasks leveraging the SAS Viya CLI and you are confident in the security of the credentials.json file you could leave the SAS Viya CLI authenticated. The SAS Viya CLI would then continue to refresh the Access Token until the Refresh Token expires, after 90 days.
Since the Refresh Token produced by the SAS Viya CLI will be valid for 90 days and can be used to obtain an Access Token, being able to revoke the Refresh Token is important. If you are administrating a SAS Viya environment and are concerned that some of your end-users might not remember to use the command sas-viya auth logout to revoke their own token. Then you could revoke all Refresh Tokens issued to the SAS Viya CLI on a regular basis. You will need to have a Bearer token as a member of SAS Administrators or the sasboot user.
To revoke the Refresh Tokens issued to users of the SAS Viya CLI you would use:
curl -i -X GET "${INGRESS_URL}/SASLogon/oauth/token/revoke/client/sas.cli" -H "Authorization: Bearer $BEARER_TOKEN"
Which would output:
HTTP/1.1 200
Date: Tue, 29 Nov 2022 12:35:02 GMT
Content-Length: 0
Connection: keep-alive
Set-Cookie: sas-ingress-nginx=a772dad7648bc6f096fb118a58701b7e|f8c52217c576225c1e53519ff3193724; Path=/SASLogon/; Secure; HttpOnly; SameSite=Lax
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=15724800; includeSubDomains
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
After this, anyone using the SAS Viya CLI would need to reauthenticate once their Access Token has expired. But it would not impact any existing Access Tokens.
If you define your own clients to SAS Logon Manager, you will need to decide about the correct lifetime values you want to use for the Access Tokens. You can override the system-wide default for your custom applications by updating the value for the access_token_validity property. See Register an OAuth Client ID in SAS Viya: Authentication for information about the access_token_validity property and the steps for registering a client so that it can obtain tokens.
For example, say you have registered a client to SAS Logon Manager with the following settings:
curl -k -X POST "${INGRESS_URL}/SASLogon/oauth/clients" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"client_id": "test.app",
"client_secret": "myclientsecret",
"scope": ["*"],
"authorized_grant_types": ["password","authorization_code","refresh_token"],
"access_token_validity": 300,
"redirect_uri": "urn:ietf:wg:oauth:2.0:oob"
}'
This will allow end-users to authenticate with either their username and password or using the authorization code. This client will produce Access Tokens with a lifetime of 5 minutes but will use the system wide default of 90 days for the lifetime of the Refresh Tokens. With this client you could then authenticate with a username and password to obtain the end-users Access Token and Refresh Token with the following:
AUTH_RESP=$(curl -skX POST "${INGRESS_URL}/SASLogon/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=password&username=sasadm&password=Metadata0" \
-u "test.app:myclientsecret"); \
USER_TOKEN=$(echo $AUTH_RESP|jq -r '."access_token"'); \
USER_REFRESH=$(echo $AUTH_RESP|jq -r '."refresh_token"'); \
echo "The end-user access-token is: " ${USER_TOKEN}; \
echo "The end-user refresh-token is: " ${USER_REFRESH}; \
echo "Expiry date of Access Token is: $(printf '%(%FT%T%z)T\n' $(echo ${USER_TOKEN}|awk -F'.' '{print $2}'|base64 -d|jq -r '."exp"'))"
Which would produce an output something like the following:
The end-user access-token is: eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vbG9jYWxob3N0L1NBU0xvZ29uL3Rva2VuX2tleXMiLCJraWQiOiJsZWdhY3ktdG9rZW4ta2V5IiwidHlwIjoiSldUIn0.
eyJqdGkiOiIxNzUwZThkZmNlM2Y0Zjc2YTA3YTNmN2FjZTVkNWQyYSIsImV4dF9pZCI6ImNuPVNBUyBBZG1pbmlzdHJhdG9yLG91PUFBRERDIFVzZXJzLGRjPWdlbGVuYWJsZSxkYz1zYXMsZGM9Y29tIiwic3ViIjo
iNjVjYTdjZDctZmM4Yi00OGNiLTgyMTAtNWRmYmJhYTIxNmZkIiwic2NvcGUiOlsiU0FTIEFkbWlucyIsIkhSIiwiU0FTIFVzZXJzIiwiU2FsZXMiLCJBbGwgR0VMQ29ycCBVc2VycyIsIkdFTFN5c3RlbUFkbWlucy
IsIkZpbmFuY2UiLCJvcGVuaWQiLCJQb3dlclVzZXJzIiwiU0FTQWRtaW5pc3RyYXRvcnMiXSwiY2xpZW50X2lkIjoidGVzdC5hcHAiLCJjaWQiOiJ0ZXN0LmFwcCIsImF6cCI6InRlc3QuYXBwIiwiZ3JhbnRfdHlwZ
SI6InBhc3N3b3JkIiwidXNlcl9pZCI6IjY1Y2E3Y2Q3LWZjOGItNDhjYi04MjEwLTVkZmJiYWEyMTZmZCIsIm9yaWdpbiI6ImxkYXAiLCJ1c2VyX25hbWUiOiJzYXNhZG0iLCJlbWFpbCI6InNhc2FkbUBnZWxlbmFi
bGUuc2FzLmNvbSIsImF1dGhfdGltZSI6MTY2OTczNjYxMSwicmV2X3NpZyI6IjRiN2U4NiIsImlhdCI6MTY2OTczNjYxMSwiZXhwIjoxNjY5NzM2OTExLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0L1NBU0xvZ29uL29
hdXRoL3Rva2VuIiwiemlkIjoidWFhIiwiYXVkIjpbInRlc3QuYXBwIiwib3BlbmlkIiwidGVzdC4qIl19.sIBcRkWLAUIZy6nGGRxtiAVIrJ4eVxykYJpqakFN25ln6ctnXd-gK7fXcL6qy2Xu0EVstI8j-OoCrTJ9L
m7WrXAMz_p2oCKHnsF4b7Cu9g-S0OjNSYKGCg8qctAVSaUuPeAtZoHopnPLe1P9Jrn1_bXzgCy0TwVW3dBj-BXjmz5GSXUy5_ru6UjPQ8EwQkvTAbFyYX1aBo8iyAcMgmehIV14C1JfIjClXBI0sWF4icZLsS_6eIv5
sy_p5U-BD8dP5wbj59qIuHBxvB0ZhOgyMqlhPO84QpPds0AhuiDe3GAeFBbybr578kFaaYxDP8GXE_pJEgnm8bx99VMpkZVucA
The end-user refresh-token is: eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vbG9jYWxob3N0L1NBU0xvZ29uL3Rva2VuX2tleXMiLCJraWQiOiJsZWdhY3ktdG9rZW4ta2V5IiwidHlwIjoiSldUIn0.
eyJqdGkiOiJlMzMyNjFiMzY4NzU0OTgzYTNhYWM1OWFhZmIwNTIzZS1yIiwic3ViIjoiNjVjYTdjZDctZmM4Yi00OGNiLTgyMTAtNWRmYmJhYTIxNmZkIiwiaWF0IjoxNjY5NzM2NjExLCJleHAiOjE2Nzc1MTI2MTEs
ImNpZCI6InRlc3QuYXBwIiwiY2xpZW50X2lkIjoidGVzdC5hcHAiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0L1NBU0xvZ29uL29hdXRoL3Rva2VuIiwiemlkIjoidWFhIiwiYXVkIjpbInRlc3QuYXBwIiwib3Blbmlk
Il0sImdyYW50ZWRfc2NvcGVzIjpbIlNBUyBBZG1pbnMiLCJIUiIsIlNBUyBVc2VycyIsIlNhbGVzIiwiQWxsIEdFTENvcnAgVXNlcnMiLCJHRUxTeXN0ZW1BZG1pbnMiLCJGaW5hbmNlIiwib3BlbmlkIiwiUG93ZXJV
c2VycyIsIlNBU0FkbWluaXN0cmF0b3JzIl0sImFtciI6WyJleHQiLCJwd2QiXSwiYXV0aF90aW1lIjoxNjY5NzM2NjExLCJleHRfaWQiOiJjbj1TQVMgQWRtaW5pc3RyYXRvcixvdT1BQUREQyBVc2VycyxkYz1nZWxl
bmFibGUsZGM9c2FzLGRjPWNvbSIsImdyYW50X3R5cGUiOiJwYXNzd29yZCIsInVzZXJfbmFtZSI6InNhc2FkbSIsIm9yaWdpbiI6ImxkYXAiLCJ1c2VyX2lkIjoiNjVjYTdjZDctZmM4Yi00OGNiLTgyMTAtNWRmYmJh
YTIxNmZkIiwicmV2X3NpZyI6IjRiN2U4NiJ9.S78JjwjNCsg43fpIPYAsIv5TEzxBSXc8KHcJj7cMWCSnXB4BIMfBSKOFya8lqRbZ7jSB1XUqC2oouWQVvMSoDEg8FtHTR3hIBiVepBFpSkJqH8LCjbWXdoJWww6WgWy
UJOKSdi3T45JecXISx5BSCgQKdxUcW5-KXW8_d1CaFbCIgFoGumFHkqdmOr6m4TRmfTYF1HeZLrYgQ6V5XfavVVkAwPqAA7QOMGQzBLkk7k-n-v8yMrrZLGeMNnwdz8CMJ82M6QC4LFZe0cv--k2KXEp_UdDWk_GeN19
zuk9a2NlicA-J-2G-NCWh1GfYo8uc1Ayo14f-XYcVTNDGVyRkJQ
Expiry date of Access Token is: 2022-11-29T10:48:31-0500
You could then use the Refresh Token to obtain a new Access Token with the following:
AUTH_RESP=$(curl -skX POST "${INGRESS_URL}/SASLogon/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=test.app&client_secret=myclientsecret&grant_type=refresh_token&refresh_token=${USER_REFRESH}"); \
USER_TOKEN=$(echo $AUTH_RESP|jq -r '."access_token"'); \
echo "The end-user access-token is: " ${USER_TOKEN}; \
echo "Expiry date of Access Token is: $(printf '%(%FT%T%z)T\n' $(echo ${USER_TOKEN}|awk -F'.' '{print $2}'|base64 -d|jq -r '."exp"'))"
Which would produce the following:
The end-user access-token is: eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vbG9jYWxob3N0L1NBU0xvZ29uL3Rva2VuX2tleXMiLCJraWQiOiJsZWdhY3ktdG9rZW4ta2V5IiwidHlwIjoiSldUIn0.
eyJqdGkiOiJmZmI3MWUxMDZmMTA0NWY0YWUxODI4NDdjNDdhOGFjMSIsImV4dF9pZCI6ImNuPVNBUyBBZG1pbmlzdHJhdG9yLG91PUFBRERDIFVzZXJzLGRjPWdlbGVuYWJsZSxkYz1zYXMsZGM9Y29tIiwiYW1yIjp
bImV4dCIsInB3ZCJdLCJzdWIiOiI2NWNhN2NkNy1mYzhiLTQ4Y2ItODIxMC01ZGZiYmFhMjE2ZmQiLCJzY29wZSI6WyJTYWxlcyIsIkFsbCBHRUxDb3JwIFVzZXJzIiwiU0FTQWRtaW5pc3RyYXRvcnMiLCJGaW5hbm
NlIiwib3BlbmlkIiwiU0FTIEFkbWlucyIsIkdFTFN5c3RlbUFkbWlucyIsIkhSIiwiU0FTIFVzZXJzIiwiUG93ZXJVc2VycyJdLCJjbGllbnRfaWQiOiJ0ZXN0LmFwcCIsImNpZCI6InRlc3QuYXBwIiwiYXpwIjoid
GVzdC5hcHAiLCJncmFudF90eXBlIjoicGFzc3dvcmQiLCJ1c2VyX2lkIjoiNjVjYTdjZDctZmM4Yi00OGNiLTgyMTAtNWRmYmJhYTIxNmZkIiwib3JpZ2luIjoibGRhcCIsInVzZXJfbmFtZSI6InNhc2FkbSIsImVt
YWlsIjoic2FzYWRtQGdlbGVuYWJsZS5zYXMuY29tIiwiYXV0aF90aW1lIjoxNjY5NzM2NjExLCJyZXZfc2lnIjoiNGI3ZTg2IiwiaWF0IjoxNjY5NzM2NzMzLCJleHAiOjE2Njk3MzcwMzMsImlzcyI6Imh0dHA6Ly9
sb2NhbGhvc3QvU0FTTG9nb24vb2F1dGgvdG9rZW4iLCJ6aWQiOiJ1YWEiLCJhdWQiOlsidGVzdC5hcHAiLCJvcGVuaWQiXX0.nTzDb6C5FjCksk1xyViXIwgl9vG1X7_6aSF4rYOYkkffTOvFt85JRsXfvycUOxVB1i
DAa2KKTF8yWX0n7XhTROnERP99SVsLoNwX-umuiE_K-uvpHQ_Ec5dYx1N-pRD8aJ3Cw-9TTrgwsmdVDc0VeN_cBhhf155F7EOd5U8uh3-FlLOMFoZ_dq4xSgBlM3uGRzm04OmMvOOxKZr6egFi0pzjZWjcfTW6N6a9U
JjGkjobhLWrAiiwCqT6ddyNLhhh_Piq9rmtsSkwdJmTT7WXx3WLxyd1f4UAbL2HGsz02awNcrg64aZfmFfWnTVAipEXcxazjGgsWLyW1VxRgEeTSA
base64: invalid input
Expiry date of Access Token is: 2022-11-29T10:50:33-0500
These simple CURL examples demonstrate how you could use the Refresh Token for your own custom clients of SAS Logon Manager. Notice that in this case the Refresh Token is a Signed JSON Web Token, not an opaque token, and is not revokable.
With the SAS Viya 2022.10 Stable release the Access Token now has a default lifetime of 1 hour while the Refresh Token has a default lifetime of 90 days. In this blog we have shown how the SAS Viya CLI will automatically refresh the Access Token so long as the Refresh Token is still valid. Equally, we have shown how you can easily revoke these long-lived Refresh Token’s ensuring that you can force your end-users to reauthenticate. Finally, we have also discussed how these token lifetimes might impact your custom clients of SAS Logon Manager, and how you can also leverage the Refresh Token.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning and boost your career prospects.