<jupyter_start><jupyter_text>AuthenticationThe following scripts register a client (one-time process) and generate an access token for use cases in the repository. To find the value of the client_token (Consul token) variable:**In SAS Viya 3.5:** cat /opt/sas/viya/config/etc/SASSecurityCertificateFramework/tokens/consul/default/client.token  **In SAS Viya 202x.x:** kubectl -n sse get secret sas-consul-client -o jsonpath="{.data.CONSUL_TOKEN}" | echo "$(base64 -d)"  Import modules, assign variables<jupyter_code>library("httr")
library("jsonlite")

#Global variables to assign:
sasserver  <- "http://your-server"
client_token <- "<PASSWORD>" # get from SAS Viya server
client_name <- "r_client" ## create your client
client_secret <- "r_secret" ## create your password
username <- "viya_user"
password <- "<PASSWORD>"<jupyter_output><empty_output><jupyter_text>Create Required Functions  Get Client Token<jupyter_code>#  Get Client Token
#  Parameters: 
#     - host = hostname 
#     - client_token (get on your SAS Server on this path: 
#     /opt/sas/viya/config/etc/SASSecurityCertificateFramework/tokens/consul/default/client.token)
#  Outputs:
#     - This call will generate a token, save it for the next call (where it says 'token_from_call_above')

#  Call: 

get_access_token <- function(host, client_token, verbose = FALSE) {

url <- parse_url(host)
url$path <- "/SASLogon/oauth/clients/consul"
url$query <- list(
  "callback" = "false",
  "serviceId" = client_name
)

response <- POST(
  url = build_url(url),
  add_headers(
    "X-Consul-Token"= client_token
  ),
  
  if(verbose) verbose()
)

stop_for_status(response)
idToken <- fromJSON(content(response, as = "text", encoding = "UTF-8"))
return(idToken)

}<jupyter_output><empty_output><jupyter_text>Register Client<jupyter_code>#  Register Client
#  Parameters: 
#     - host = hostname
#     - idToken = access token from consul idToken$access_token
#     - client_name
#     - client_secret
#  Outputs:
#      - It will return the client created

# Call:

register_client <- function(host, idToken, client_name, client_secret, 
                            verbose = FALSE, scope = list("openid","uaa.admin")) {

  url <- parse_url(host)
  url$path <- "/SASLogon/oauth/clients"
  
  body <- list(
    "client_id" = client_name,
    "scope" = scope,
    "access_token_validity" = 36000,
    "client_secret" = client_secret,
    "resource_ids" = "none",
    "authorities" = "uaa.none",
    "authorized_grant_types"= "password"
  )
  
  response <- POST(
    url = build_url(url),
    add_headers(
      "Content-Type"="application/json",
      "authorization" = paste("Bearer", idToken)
      ),
    body = toJSON(body, auto_unbox = T),
    if(verbose) verbose()
  )
  
  stop_for_status(response)
  registered_client <- fromJSON(content(response, as = "text", encoding = "UTF-8"))
  return(registered_client)
}<jupyter_output><empty_output><jupyter_text>Get API call token<jupyter_code>#  Get API call token
#  Paremeters:
#     - your_server
#     - (Base64) encoded_client_secret
#     - your_username
#     - your_passwordc
#  Outputs:
#     - It will return a JSON, you will use the access_token for future calls

# Call:


authenticate <- function(host, username, password,
                         client_name, client_secret, 
                         verbose = FALSE) {
  
  client_info <- base64_enc(paste0(client_name, ":", client_secret))
  
  url <- parse_url(host)
  url$path <- "/SASLogon/oauth/token"
  url$query <- list(
    grant_type = "password",
    username = username,
    password = password 
  )
  
  response <- GET(
    url = build_url(url),
    add_headers(
      "Content-Type" = "application/x-www-form-urlencoded",
      "accept"="application/json",
      "authorization" = paste("Basic", client_info)
    ),
    
    if(verbose) verbose()
  )
  
  stop_for_status(response)
  registered_clients <- fromJSON(content(response, as = "text", encoding = "UTF-8"))
  return(registered_clients)
}<jupyter_output><empty_output><jupyter_text>Create Optional Functions  List Clients<jupyter_code>#  List available Clients
#  Parameters: 
#     - host = hostname
#     - idToken = access token from consul idToken$access_token
#     - startIndex = starting intex from the client results
#     - count = number of clients to return
#     - cliunt_id_filter = simple regex filter for name search
#  Outputs:
#      - It will return a list of clients with its properties

# Call:

list_clients <-  function(host, idToken,
                          startIndex = 1, count = 30, 
                          clind_id_filter = "",
                          verbose = FALSE) {
  
  url <- parse_url(host)
  url$path <- "/SASLogon/oauth/clients"
  url$query <- list(
    filter = paste0('client_id co "', clind_id_filter, '"'),
    sortBy = "client_id",
    startIndex = startIndex,
    count = count
  )
  
  response <- GET(
    url = build_url(url),
    add_headers(
      "accept"="application/json",
      "authorization" = paste("Bearer", idToken)
    ),
    
    if(verbose) verbose()
  )
  
  stop_for_status(response)
  registered_clients <- fromJSON(content(response, as = "text", encoding = "UTF-8"))
  return(registered_clients)
}<jupyter_output><empty_output><jupyter_text>Delete Client<jupyter_code>#  Delete Client
#  Parameters: 
#     - host = hostname
#     - access_token = access token obtained with authenticate()
#     - the access_token client must have one of these scopes:
#       uaa.admin clients.write clients.admin zones.uaa.admin
#     - client_id = client_name
#  Outputs:
#      - It will return a list of clients with its properties

# Call:

delete_client <- function(host, access_token,
client_id,
verbose = FALSE) {
url <- parse_url(host)
url$path <- paste0("/SASLogon/oauth/clients/", client_id)
response <- DELETE(
url = build_url(url),
add_headers(
"accept"="application/json",
"authorization" = paste("Bearer", token$access_token)
),
if(verbose) verbose()
)
warn_for_status(response)
if (status_code(response) == "404"){
warning("Even with an 404 error, it is probable the client was successfully deleted")
return(response)} else{
deleted_client <- fromJSON(content(response, as = "text", encoding = "UTF-8"))
return(deleted_client)
}
}<jupyter_output><empty_output><jupyter_text>Update Client Secret<jupyter_code>#  Update Client Secret
#  Parameters: 
#     - host = hostname
#     - access_token = access token obtained with authenticate()
#     - the access_token client must have one of these scopes:
#       uaa.admin clients.secret clients.admin zones.uaa.admin
#     - client_id = client_name
#  Outputs:
#      - It will return a list of clients with its properties

# Call:

update_client_secret <-  function(host, access_token,
                           client_id,
                           new_secret,
                           verbose = FALSE) {
  
  url <- parse_url(host)
  url$path <- paste0("/SASLogon/oauth/clients/", client_id, "/secret")
  
  body <- list(clientId = client_id,
               secret = new_secret)
  
  response <- PUT(
    url = build_url(url),
    add_headers(
      "Content-Type" = "application/json",
      "accept"="application/json",
      "authorization" = paste("Bearer", access_token)
    ),
    body = toJSON(body, auto_unbox = T),
    
    if(verbose) verbose()
  )
  
  stop_for_status(response)
  secret_update <- fromJSON(content(response, as = "text", encoding = "UTF-8"))
  return(secret_update)
}<jupyter_output><empty_output><jupyter_text>Run Required FuncitonsRecall, you only register the client once.<jupyter_code># Get Client Token
idToken <- get_access_token(host = sasserver ,
                            client_token = client_token)
# Register Client
client <- register_client(host = sasserver ,
                idToken = idToken$access_token,
                client_name = client_name,
                client_secret = client_secret)
# Get Access Token
token <- authenticate(host = sasserver ,
                      username = username,
                      password = password,
                      client_name = client_name,
                      client_secret = client_secret)

token$access_token ## for use in optional calls
token<jupyter_output><empty_output><jupyter_text>Run Optional Functions<jupyter_code># List available clients
client_list <- list_clients(host = sasserver ,
                      idToken = idToken$access_token)
client_list
# Delete clients
del_cli <- delete_client(sasserver,
                        access_token = token$access_token,
                        client_id = "r_client_erase")
# Update client secret
secret_up <- update_client_secret(sasserver,
                                  access_token = token$access_token,
                                  client_id = client_name,
                                  new_secret = "new_r_secret",
                                  verbose = FALSE)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11303667262969588, 'fraction_numerical': 0.0039132379248658315, 'mean_word_length': 3.0148114901256733, 'pattern_counts': {'":': 1, '<': 87, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '428403', 'license': 'Apache-2.0', 'n_tokens_mistral': 2921, 'n_tokens_neox': 2785, 'n_words': 648, 'path': 'r/authentication/authentication-r.ipynb', 'repo_name': 'sassoftware/rest-api-use-cases', 'size': '8949'}