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.

  1. User in the SAS Administrators group generates access token to register a new Client ID
  2. Use the access token to register the new client ID and secret
  3. Obtain the authorization code
  4. Acquire the OAuth access token of the Client ID using the authorization code
  5. 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" \
-u "sas.cli:" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d '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 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 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.

  1. Use the SAS Viya configuration server's Consul token to obtain an access token to register a new Client ID
  2. Use the access token to register the new client ID and secret
  3. Obtain the authorization code
  4. Acquire the OAuth access token of the Client ID using the authorization code
  5. 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.

Share

About Author

Joe Furbee

Developer Advocate

As a developer advocate and community manager at SAS, Joe serves as a liaison between the developer community and SAS technologies. He oversees developer.sas.com, which provides resources for developers on SAS and open source, and writes blogs on programming and SAS administration tips. Recently, Joe was recognized by WhiteSource software in their list of Top 20 developer advocates to follow in 2020. Joe is passionate about chronicling his journey as he expands his own knowledge-base of SAS and open source integration.

62 Comments

  1. Thanks for very informative article, i have a question, is authorization code flow, not possible without a man in middle? i.e. without user login to browser. i want to build an app using viya rest api's, but want to use a fixed user as of now. dont want to use client_credentials as doesn't allow to login to UI. is there a way this can be done? and i dont want to use password flow due to obvious reasons

  2. I'm working with a SAS Viya 3.5. Everything works fine until the Authorization Code, but VSS complains about the certificate (self-signed certificate message).
    I've seen a section about user-provided Certificates in the extension settings. Could you explain whether I should put the certs text, the file, or something else?
    I'm using the CA bundle in /opt/sas/viya/home/SASSecurityCertificateFramework/tls/certs.
    Thanks

    • Joe Furbee

      Hi Andrea,
      I spoke with our auth developer and he believe this is most likely something specific to your environment and not related to the content in this post. He recommended open a ticket with Tech Support.

  3. Hi Jo

    Great blog!

    I'm trying to connect Enterprise Guide 8.3 to Viya 3.5 SPRE. Connectivity is working fine but I need to generate and set VIYA_AUTH_TOKEN to access the credentials service to get access to authdomains. If I use grant_type=password to obtain a token, I can use it in a set SAS_VIYA_TOKEN statement and assign my libraries using authdomain=. As Hubert pointed out earlier, this requires a clear text password which I would also like to avoid.

    If I use grant_type=client_credentials (after registering an oauth client) or I use grant_type=authorization_code I successfully obtain a token but it's not valid as a VIYA_AUTH_TOKEN. I get an authentication error trying to access the authdomains. The token is significantly shorter than the token obtained using grant_type=password. About half the length, if that's relevant.

    Have you seen and solved this behaviour before?

    Or, is it possible for a Viya Spawner launched Workspace server to obtain a VIYA_AUTH_TOKEN by another method?

    Thanks,

    Jonathan.

    • Joe Furbee

      Hi Harald,
      I'm not familiar with the ops-util command. Is this a CLI command? I could not find it in the documentation.
      As for a REST call to unregister a client, the documentation is here and here is an example call, using curl and deleting the client_id api.client:
      curl -k -X DELETE 'https://sasserver.sas.com/SASLogon/oauth/clients/api.client' --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImprdS.........'

  4. Tim Bedsted on

    Hello

    I am using Windows powershell.

    It does not recognize the Export command, so how can I accomplish the first step of storing the token?

    • Joe Furbee

      Hi Tim,
      Thanks for reaching out. To create a variable using Powershell, you can use the following syntax $env:TOKEN = "ABCD-123". Here's a link to more info on variables and Powershell.
      Specifically for this instance, it may be easier to run the curl command without the variable assignment, copy the access token that is returned, then use the code above and assign the value.

  5. Hi Joe,

    I'm trying to follow this process on a Viya4 environment but getting an error from the curl command in step 2 - request body missing or invalid. My colleague has run the exact same command successfully on 3.5. Any thoughts/suggestions here?!

  6. Hi Joe

    Does the sas-viya CLI require the use of refresh tokens to operate? I am generating access tokens using a client_credentials grant type and would like to use this to invoke batch commands using the CLI. However it seems the CLI references its credentials.json file with always contains both an access token AND a refresh token. Commandline invocations do not complete if he refresh token is not present in that file. Is this a requirement of the CLI - or is there a way to use valid access tokens from another source? ... for example, an external token manager.

  7. Pascal Nicolas on

    Hi Joe,
    Thank you for your post.

    I would like to execute a SASJobExecution from an excel spreadsheet.
    I tested it on a test environment (SAS RACE environment) and I worked correctly.

    But on the customer site, I have a error with the grant_type=password usage.

    When I call URL to get a TOKEN with grant_type=password, I receive this message :
    {"error":"invalid_client","error_description":"Unauthorized grant type: password"}

    I execute this command :
    curl -k https://myhost/SASLogon/oauth/token -H "Content-Type: application/x-www-form-urlencoded" -u "appid:appsecret" -d "grant_type=password&username=myemail&password=mypwd"

    When I execute the curl query of step 5 to list folders, it's ok.

    Do you have any idea on this ?

    Regards,
    Pascal

    • Pascal Nicolas on

      I used the grant_type=client_credentials in place of password mode.
      It seems to be ok.
      With grant_type=client, is it mandatory to have ssl cetificat on the client desktop to use it ?

      Regards,
      Pascal

      • Joe Furbee

        Hi Pascal,
        It is not required to have the ssl cert on the client when using client_credentials grant type. It will depend on your environment and if and how TLS is set up. Things can get hairy pretty quickly in this area.

        I've worked around ssl issues by configuring API calls from Postman and Python to ignore it. This may not be the most secure, but it satisfies my testing needs.

    • Joe Furbee

      Hi Pascal,
      The error indicates an issue with the clientid. When you created the client did you indicate the password grant type? Something like the following:
      "authorized_grant_types": ["password","refresh_token"]

      The grant type in the registration steps has to match the grant type in the access token request.

      As for the success of the call in step 5, what access token are you passing in the header and where did it come from?
      -H "Authorization: Bearer $ACCESS_TOKEN"

    • Joe Furbee

      Hi Stian,
      The refresh token ttl is 30 days. You are correct that you have to get a new authorization code to start the process over. This is done for security purposes. You can extend the ttl of the access token when you create it to however long you'd like; however, again, this can lead to security issues. Here are links to a couple of threads in the SAS Support Community dealing with tokens that you may find of interest:
      Refresh token Validity in Viya 3.5
      VIYA api access best practice

  8. As an administrator, we have a series of various groups looking to create some integrations. In order to more efficiently manage clients is there a GUI solution available in Environment Manager to help?

  9. Ji Joe,
    interesting blog entries.
    customer ask if there is a method/technique to hide the plain text passwords when requesting a access token. They're doing it that way...

    curl -X POST "/SASLogon/oauth/token" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "grant_type=password&username=&password=" \
    -u ":"

    thanks in advance

  10. Thanks for these instructions – very helpful. I was able to register the client and get an access code using the password, but when I try to use the access code to call an API, I get the message “Full authentication is required to access this resource”. I also get this message when I go to the SASLogon/oauth/clients address. Any clues as to what I might be missing?

    • Joe Furbee

      Hi Julie,
      Thanks for reading and your question. The error you received is pretty generic and could be a number of things (most likely easily solvable). If you don't mind, this may be easier to troubleshoot by creating a new thread in the Developers Community. There you'll be able to provide more details about what you did and we can investigate further. I monitor the community and will see your request come through.

      Thanks,
      Joe

    • Joe Furbee

      Hi Hussein,
      Thanks for reading and your inquiry. Yes, you can access SAS Visual Analytics APIs using the access token generated in this post. Many of the APIs you may want to explore are documented in the Visualization API on developer.sas.com.

      I would also highly recommend exploring the Visual Analytics SDK.

  11. Hi Joe,

    Thanks for this post. My question is related to CAS APIs. With the access tokens generated using above methods, I was able to load a csv in caslib public. However, with the same token if I try to create a global caslib it fails with "ERROR: You do not have permission to create global caslibs." With the credentials I supplied while creating the access tokens if I login to Environment Manager, I can create a global caslib. I can even use the credentials in curl with -u user:password and can successfully create global caslib.

    Can you tell what is preventing from creating a global caslib using access tokens generated by the steps you outline above? I verified that the identity I used to generate access tokens is present in 'caslib management privileges'. In short, do you know how to add the registered client (from step 2 above) in 'caslib management privileges'?

    Thanks,
    Pravin

    • Joe Furbee

      Hi Pravin,
      I'm still looking into this, but the first thing that comes to mind is to check/verify the 'scopes' used during client registration. If you have the ability to re-register your client, try with scope: ['openid', '*']. You can read more about authentication on SAS Viya in this SASGF paper: OpenID Connect Opens the Door to SAS® Viya® APIs.

      Also, what client are you using to make the request? What REST endpoint are you using? Can you provide the entire call?

      • curl -s -X POST https://example.abc.com:8777/cas/sessions/58487c47-5ed6-de4d-b77b-1672b7c27d3d/actions/table.addCaslib -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" -d '{"name":"pcas","path":"/data/pcas","description":"Pravin caslib","subDirectories":"false","session":"false","dataSource":{"srcType":"path"},"createDirectory":"true","hidden":"false","transient":"false"}'

        results in

        "logEntries": [
        { "message": "NOTE: The specified directory for caslib pcas already exists.", "level": "info" },
        { "message": "ERROR: You do not have permission to create global caslibs.", "level": "error" },
        { "message": "ERROR: The action stopped due to errors.", "level": "error" }
        ],

        • Joe Furbee

          Hi Pravin,
          I could not replicate your issue. The issue could be with the scope used when registering your client (in Step 2 above).

          Can you verify the value you receive for the scope parameter when you generate the access token in Step 4 above? In my example, I see the following: "scope":"openid".

  12. Hi Joe

    In you example of generating access token using password, you have used 'clientid' and 'myclientsecret' in the client id and secret field. but while authorizing the access you have used -u "sas.cli:".
    what is this sas.cli client id, could you please give us some more insights?

    Thanks
    sounak

    • Joe Furbee
      Joe Furbee on

      Hi Sounak. Thanks for reading and your question. This is an oversight in my cURL comamnd. The -u value should be, clientid:clientsecret, which to keep consistent with my other commands throughout the post should be -u "myclientid:myclientsecret". I have made this adjustment in two place in the article. It now appears properly. Please let me know if you have further questions.

  13. jianlin huang on

    Hi, Does a user password change affect the generated access_token (it will expire, or no effect?) . Thanks.

    • Joe Furbee

      Hi Jianlin,
      Great question! The answer is 'No', a password change will not revoke the access token generated using grant_type=password. SAS Viya does not store the password when creating the access token, so it would not know when a user's password changes.

      Thanks,
      Joe

      • jianlin huang on

        Hi Joe,
        Thanks for your help, I have a project here where a client needs a Token when calling the VIYA REST API, and I'm thinking if I can just give a long-term valid Token. So that what happens when Token becomes unavailable, like a system reboot, migration? In addition, do you know where the Token information exists and what commands are available to view all them in the system? Thanks again.

        • Joe Furbee
          Joe Furbee on

          Hi Jianlin. In some instances you may have to regenerate the token. You can follow the same steps listed in the article to get the original token. You can also consider using a refresh token. Below I've listed questions/answers from an earlier comment that may apply here:

          I assumed the REFRESH_TOKEN would not expire, but it did. -- REFRESH_TOKENS expire 30 days after being issued by SAS Viya; this is a configurable value on SAS Viya; see below for more details.

          Note: If you use the REFRESH_TOKEN to get a new ACCESS_TOKEN, a new REFRESH_TOKEN is generated, but has the same ttl as the original REFRESH_TOKEN, not 30 additional days.

          If the REFRESH_TOKEN expires, what is the action to take? -- You will need to go to the user again to get a new REFRESH_TOKEN. Request a new ACCESS_TOKEN using the authorization code grant type.

          Is it possible to not have an expiration date for the REFRESH_TOKEN ? -- The REFRESH_TOKEN lifetime and ACCESS_TOKEN lifetime can be extended out as far as you want (1 year, 20 years, etc.) See the sas.logon.jwt configuration in SAS EV.

          I hope this helps and if you have further questions, please let me know.

          • jianlin huang on

            Thank you very much, if I set ACCESS_TOKEN to not expire (e.g10 years), and don't need to use REFRESH_TOKEN, is that okay? Of course there may be some safety issues.

    • Joe Furbee

      Hi Lei,
      Thanks for reading the post and your question. Are you referencing authorization or authentication? Providing a bit more context around your question will assist us in providing a complete answer. Thanks!

  14. Richard Paterson on

    Hi, first of all thanks for this excellent guide. I have my cURL statement working perfectly. I would however like to run this command via PROC HTTP and this is where things come unstuck.

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

    I am having difficulty understanding the -u switch in the cURL statement. What is "sas.cli:"? and where do I specify this in the PROC HTTP code ? So far I have this,

    proc http url="http://sasviya01.race.sas.com/SASLogon/oauth/token" method="GET" auth_basic
    in="grant_type=password"
    webauthdomain="sas.cli:"
    webusername="geladm"
    webpassword="lnxsas"
    out=response
    headerout=hdrout
    headerout_overwrite;
    headers "Accept"="application/json";
    run;

    but this is giving me an access error.

    any help would be very much appreciated!

    regards,

    Richard

  15. Hi Joe,

    I am a novice developer trying to implement and learn something.

    For step 2: "client_id": "myclientid",
    "client_secret": "myclientsecret"

    I do not have an API or client that I can use here. What are the default values or can I make up anything? and use it later for authentication.

    I tried to use client_id: report and a generic secret, and I was able to run this code

    curl -X POST "https://sasvad01.wcuds.net/SASLogon/oauth/clients" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $IDTOKEN" \
    -d '{
    "client_id": "report",
    "client_secret": "test",
    "scope": ["openid"],
    "authorized_grant_types": ["password"],
    "access_token_validity": 43199
    }'

    but then I am stuck in step 3. When I try to access the url with the client name it says : The request is invalid.
    A redirect_uri can only be used by implicit or authorization_code grant types.

    Can you please let me know how to delete the clients?

    I also tried this:

    curl -k -X POST "https://sasvad01.wcuds.net/SASLogon/oauth/clients" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $IDTOKEN" \
    -d '{
    "client_id": "report2",
    "client_secret": "test",
    "scope": ["openid"],
    "authorized_grant_types": ["authorization_code","refresh_token"],
    "redirect_uri": "urn:ietf:wg:oauth:2.0:oob"
    }'
    {"scope":["openid"],"client_id":"report","resource_ids":["none"],"authorized_grant_types":["refresh_token","authorization_code"],"redirect_uri":["urn:ietf:wg:oauth:2.0:oob"],"autoapprove":[],"authorities":["uaa.none"],"lastModified":1547138692523,"required_user_groups":[]}

    but it said
    -bash: scope:[openid]: command not found

    • Joe Furbee

      Hi Ravi,
      First, to delete clients, please see the previous comment from Edo on April 21, 2019 6:10 pm. The answer to your question can be found there.

      As for the clientid question, this is the trickiest part of getting started. You'll need to register the client first and to do this you'll need admin privileges or have someone with admin complete the task outlined in this documentation. Here is another set of instructions for completing the same task from developer.sas.com. To summarize what to do:

      1. Locate a valid Consul token - usually found here: /opt/sas/viya/config/etc/SASSecurityCertificateFramework/tokens/consul/default/client.token
      2. Request an OAuth token to use on the registration call - The sample command below is for registering a client named "report"
      curl -X POST "http://example.com/SASLogon/oauth/clients/consul?callback=false&serviceId=report" -H "X-Consul-Token: \"
      3. The command above will return an access_token. Use the token in the command below to register the client (you can leave the client_secret: value blank).
      curl -X POST "https://localhost/SASLogon/oauth/clients" -H "Content-Type: application/json" -H "Authorization: Bearer <access -token-goes-here>" -d '{"client_id": "report", client_secret": <secret -goes-here>", "scope": ["openid"], "authorized_grant_types": ["password"], "access_token_validity": 43199}'</secret></access>
      4. If the request is successful, the client is registered.
      5. You can now use "report" as the client_id in the call you posted.

      Hope this helps!

  16. Hi Joe,

    a question about this element of the token & OAuth process: "scope": ["openid", "group1"]

    Does the "group1" item refer to "Custom Groups" within Viya or to something else? Presumably this can be used to restrict access if this is the case?

    thenaks

    Alan

    • Joe Furbee

      Hi Alan,
      Scopes should always include "openid" along with any other groups that this client needs to get in the access tokens. You can specify "*" but then the user will get prompted for all their groups, which is tedious. The example in the article uses one group named "group1", but in production would be customized to fit customer needs.

      • I'm not sure I followed the answer to the question. In your example, is group1 a Custom Group within Viya, or an LDAP group? Or can it be either?
        Likewise, if I'm using this client app/secret to get a token just for autdomain support, can/should I limit the applicability of the token via the resource_ids values? Woudl I be specifiing the id of the authdomain in that scenario?

      • Hi Joe,

        I have the same question as Alan and although I think I know that the answer is: "Yes, the group you are referring to is a Viya Custom Group", I cannot get it to work correctly. (in SAS Viya LTS 2023.3)

        I am trying to create a client_id that only has 1 group membership so it will only have access permissions that follow from that one group membership:

        curl -k -X POST "${INGRESS_URL}/SASLogon/oauth/clients" \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer $BEARER_TOKEN" \
        -d '{
        "client_id": "myclientid",
        "client_secret": "xxxxxxxxxxxxxxxxxxxxxxxx",
        "scope": ["openid", "group1"],
        "authorized_grant_types": ["authorization_code","refresh_token"],
        "redirect_uri": "urn:ietf:wg:oauth:2.0:oob"
        }'

        The admin account for which the $BEARER_TOKEN was created, has several group memberships including "group1". But when I visit the url to retrieve the Authorization code (${INGRESS_URL}/SASLogon/oauth/authorize?client_id=scr_deployer&response_type=code), only ever have "openid" and "SAS Administrators" to choose from. No other groups are visible. I tried the following options for scope:
        scope": ["*"]
        scope": ["openid"]
        scope": ["openid", "*"]
        scope": ["openid", "group1"]
        scope": ["openid", "non-existent group"]
        but the result is always that I can select openid and "SAS Administrators" (if I included "*")

        What should I do to select other groups?

  17. I do not see any clients, which were added by following the instructions in this article, when calling /SASLogon/oauth/clients via GET. I only see the standard SAS Viya ones like SAS Drive,..

    (I am able to add a client, authenticate via refresh/access token, and successfully call the SAS Viya API)

    Have you seen any custom clients by calling /SASLogon/oauth/clients via GET?

    • Joe Furbee
      Joe Furbee on

      Hi C. Thanks for reading and posting your question. I went into my env and registered a dummy client - myclient using this command:
      curl -k -X POST "https://sasserver.demo.sas.com/SASLogon/oauth/clients" -H "Content-Type: application/json" -H "Authorization: Bearer $IDTOKEN" -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"}'

      I then went to Postman and ran the following GET: http://sasserver.demo.sas.com/SASLogon/oauth/clients. I received back all registered clients, including myclientid.

      Further, I filtered on myclientid with this GET: http://sasserver.demo.sas.com/SASLogon/oauth/clients/myclientid. I received the following 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": [],"authorities": ["uaa.none"],"lastModified": 1557321328647,"required_user_groups": []}

      Are these the steps you followed? Does this point you in the right direction?

  18. Hello,

    I assumed the REFRESH_TOKEN would not expire, but it did. I tried to request another ACCESS_TOKEN (continuing with a test I started a couple of weeks ago) but I got an error message returned: {"error":"invalid_token","error_description":"Invalid refresh token (expired): eyJhbGciOiJSUz...Hnses0K5UMa8 expired at Fri Apr 05 15:55:25 CEST 2019"}

    If the REFRESH_TOKEN expires, what is the action to take?

    Is it possible to not have an expiration date for the REFRESH_TOKEN ?

    Thank you!

    • Joe Furbee
      Joe Furbee on

      Hi C. Below are answers to your questions:
      I assumed the REFRESH_TOKEN would not expire, but it did. -- REFRESH_TOKENS expire 30 days after being issued by SAS Viya; this is a configurable value on SAS Viya; see below for more details.

      Note: If you use the REFRESH_TOKEN to get a new ACCESS_TOKEN, a new REFRESH_TOKEN is generated, but has the same ttl as the original REFRESH_TOKEN, not 30 additional days.

      If the REFRESH_TOKEN expires, what is the action to take? -- You will need to go to the user again to get a new REFRESH_TOKEN. Request a new ACCESS_TOKEN using the authorization code grant type.

      Is it possible to not have an expiration date for the REFRESH_TOKEN ? -- The default length for the ACCESS_TOKEN is 24 hours and 30 days for the REFRESH_TOKEN. The ACCESS_TOKEN lifetime can be extended out as far as you want (1 year, 20 years, etc.). Note, however, the limit for the REFRESH_TOKEN lifetime is 30 days (or less). This is all controlled by the sas.logon.jwt configuration property. See the sas.logon.jwt configuration in SAS EV administration documentation. on how to adjust the system defaults.

  19. How to delete a client_id? Tried to send method DELETE to /SASLogon/oauth/clients but it says it only accept GET and POST.

  20. Step 4 "app:appclientsecret" should be "myclientid:myclientsecret" if you want to be consistent with Step 2.

Leave A Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Back to Top