Macros for SAS Application Developers
https://github.com/sasjs/core
mv_tokenauth.sas
Go to the documentation of this file.
1 /**
2  @file mv_tokenauth.sas
3  @brief Get initial Refresh and Access Tokens
4  @details Before a Refresh Token can be obtained, the client must be
5  registered by an administrator. This can be done using the
6  `mv_registerclient` macro, after which the user must visit a URL to get an
7  additional code (if using oauth).
8 
9  That code (or username / password) is used here to get the Refresh Token
10  (and an initial Access Token). THIS MACRO CAN ONLY BE USED ONCE - further
11  access tokens can be obtained using the `mv_gettokenrefresh` macro.
12 
13  Access tokens expire frequently (every 10 hours or so) whilst refresh tokens
14  expire periodically (every month or so). This is all configurable.
15 
16  Usage:
17 
18  filename mc url
19  "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
20  %inc mc;
21 
22 
23  %mv_registerclient(outds=clientinfo)
24 
25  %mv_tokenauth(inds=clientinfo,code=LD39EpalOf)
26 
27  A great article for explaining all these steps is available here:
28 
29  https://blogs.sas.com/content/sgf/2019/01/25/authentication-to-sas-viya/
30 
31  @param [in] inds= A dataset containing client_id, client_secret, and auth_code
32  @param [in] outds= A dataset containing access_token and refresh_token
33  @param [in] client_id= The client name
34  @param [in] client_secret= client secret
35  @param [in] grant_type= valid values are "password" or "authorization_code"
36  (unquoted). The default is authorization_code.
37  @param [in] code= ()
38  If grant_type=authorization_code then provide the necessary code here
39  @param [in] user= If grant_type=password then provide the username here
40  @param [in] pass= If grant_type=password then provide the password here
41  @param [in] access_token_var= (ACCESS_TOKEN)
42  The global macro variable to contain the access token
43  @param [in] refresh_token_var= (REFRESH_TOKEN)
44  The global macro variable to contain the refresh token
45  @param [in] base_uri= The Viya API server location
46 
47  @version VIYA V.03.04
48  @author Allan Bowe, source: https://github.com/sasjs/core
49 
50  <h4> SAS Macros </h4>
51  @li mp_abort.sas
52  @li mf_getplatform.sas
53  @li mf_getuniquefileref.sas
54  @li mf_getuniquelibref.sas
55  @li mf_existds.sas
56 
57 **/
58 
59 %macro mv_tokenauth(inds=mv_registerclient
60  ,outds=mv_tokenauth
61  ,client_id=someclient
62  ,client_secret=somesecret
63  ,grant_type=authorization_code
64  ,code=
65  ,user=
66  ,pass=
67  ,access_token_var=ACCESS_TOKEN
68  ,refresh_token_var=REFRESH_TOKEN
69  ,base_uri=#NOTSET#
70  );
71 %global &access_token_var &refresh_token_var;
72 
73 %local fref1 fref2 libref;
74 
75 /* test the validity of inputs */
76 %mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password)
77  ,mac=&sysmacroname
78  ,msg=%str(Invalid value for grant_type: &grant_type)
79 )
80 
81 %if %mf_existds(&inds) %then %do;
82  data _null_;
83  set &inds;
84  call symputx('client_id',client_id,'l');
85  call symputx('client_secret',client_secret,'l');
86  if not missing(auth_code) then call symputx('code',auth_code,'l');
87  run;
88 %end;
89 
90 %mp_abort(iftrue=(&grant_type=authorization_code and %str(&code)=%str())
91  ,mac=&sysmacroname
92  ,msg=%str(Authorization code required)
93 )
94 
95 %mp_abort(iftrue=(
96  &grant_type=password and (%str(&user)=%str() or %str(&pass)=%str()))
97  ,mac=&sysmacroname
98  ,msg=%str(username / password required)
99 )
100 
101 /* prepare appropriate grant type */
102 %let fref1=%mf_getuniquefileref();
103 
104 data _null_;
105  file &fref1;
106  if "&grant_type"='authorization_code' then string=cats(
107  'grant_type=authorization_code&code=',symget('code'));
108  else string=cats('grant_type=password&username=',symget('user')
109  ,'&password=',symget(pass));
110  call symputx('grantstring',cats("'",string,"'"));
111 run;
112 /*data _null_;infile &fref1;input;put _infile_;run;*/
113 
114 /**
115  * Request access token
116  */
117 %if &base_uri=#NOTSET# %then %let base_uri=%mf_getplatform(VIYARESTAPI);
118 
119 %let fref2=%mf_getuniquefileref();
120 proc http method='POST' in=&grantstring out=&fref2
121  url="&base_uri/SASLogon/oauth/token"
122  WEBUSERNAME="&client_id"
123  WEBPASSWORD="&client_secret"
124  AUTH_BASIC;
125  headers "Accept"="application/json"
126  "Content-Type"="application/x-www-form-urlencoded";
127 run;
128 /*data _null_;infile &fref2;input;put _infile_;run;*/
129 
130 /**
131  * Extract access / refresh tokens
132  */
133 
134 %let libref=%mf_getuniquelibref();
135 libname &libref JSON fileref=&fref2;
136 
137 /* extract the tokens */
138 data &outds;
139  set &libref..root;
140  call symputx("&access_token_var",access_token);
141  call symputx("&refresh_token_var",refresh_token);
142 run;
143 
144 
145 libname &libref clear;
146 filename &fref1 clear;
147 filename &fref2 clear;
148 
149 %mend mv_tokenauth;