Production Ready 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 "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
19  %inc mc;
20 
21 
22  %mv_registerclient(outds=clientinfo)
23 
24  %mv_tokenauth(inds=clientinfo,code=LD39EpalOf)
25 
26  A great article for explaining all these steps is available here:
27 
28  https://blogs.sas.com/content/sgf/2019/01/25/authentication-to-sas-viya/
29 
30  @param inds= A dataset containing client_id, client_secret, and auth_code
31  @param outds= A dataset containing access_token and refresh_token
32  @param client_id= The client name
33  @param client_secret= client secret
34  @param grant_type= valid values are "password" or "authorization_code" (unquoted).
35  The default is authorization_code.
36  @param code= If grant_type=authorization_code then provide the necessary code here
37  @param user= If grant_type=password then provide the username here
38  @param pass= If grant_type=password then provide the password here
39  @param access_token_var= The global macro variable to contain the access token
40  @param refresh_token_var= The global macro variable to contain the refresh token
41  @param base_uri= The Viya API server location
42 
43  @version VIYA V.03.04
44  @author Allan Bowe
45  @source https://github.com/sasjs/core
46 
47  <h4> Dependencies </h4>
48  @li mp_abort.sas
49  @li mf_getplatform.sas
50  @li mf_getuniquefileref.sas
51  @li mf_getuniquelibref.sas
52  @li mf_existds.sas
53 
54 **/
55 
56 %macro mv_tokenauth(inds=mv_registerclient
57  ,outds=mv_tokenauth
58  ,client_id=someclient
59  ,client_secret=somesecret
60  ,grant_type=authorization_code
61  ,code=
62  ,user=
63  ,pass=
64  ,access_token_var=ACCESS_TOKEN
65  ,refresh_token_var=REFRESH_TOKEN
66  ,base_uri=#NOTSET#
67  );
68 %global &access_token_var &refresh_token_var;
69 
70 %local fref1 fref2 libref;
71 
72 /* test the validity of inputs */
73 %mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password)
74  ,mac=&sysmacroname
75  ,msg=%str(Invalid value for grant_type: &grant_type)
76 )
77 
78 %if %mf_existds(&inds) %then %do;
79  data _null_;
80  set &inds;
81  call symputx('client_id',client_id,'l');
82  call symputx('client_secret',client_secret,'l');
83  if not missing(auth_code) then call symputx('code',auth_code,'l');
84  run;
85 %end;
86 
87 %mp_abort(iftrue=(&grant_type=authorization_code and %str(&code)=%str())
88  ,mac=&sysmacroname
89  ,msg=%str(Authorization code required)
90 )
91 
92 %mp_abort(iftrue=(&grant_type=password and (%str(&user)=%str() or %str(&pass)=%str()))
93  ,mac=&sysmacroname
94  ,msg=%str(username / password required)
95 )
96 
97 /* prepare appropriate grant type */
98 %let fref1=%mf_getuniquefileref();
99 
100 data _null_;
101  file &fref1;
102  if "&grant_type"='authorization_code' then string=cats(
103  'grant_type=authorization_code&code=',symget('code'));
104  else string=cats('grant_type=password&username=',symget('user')
105  ,'&password=',symget(pass));
106  call symputx('grantstring',cats("'",string,"'"));
107 run;
108 /*data _null_;infile &fref1;input;put _infile_;run;*/
109 
110 /**
111  * Request access token
112  */
113 %if &base_uri=#NOTSET# %then %let base_uri=%mf_getplatform(VIYARESTAPI);
114 
115 %let fref2=%mf_getuniquefileref();
116 proc http method='POST' in=&grantstring out=&fref2
117  url="&base_uri/SASLogon/oauth/token"
118  WEBUSERNAME="&client_id"
119  WEBPASSWORD="&client_secret"
120  AUTH_BASIC;
121  headers "Accept"="application/json"
122  "Content-Type"="application/x-www-form-urlencoded";
123 run;
124 /*data _null_;infile &fref2;input;put _infile_;run;*/
125 
126 /**
127  * Extract access / refresh tokens
128  */
129 
130 %let libref=%mf_getuniquelibref();
131 libname &libref JSON fileref=&fref2;
132 
133 /* extract the tokens */
134 data &outds;
135  set &libref..root;
136  call symputx("&access_token_var",access_token);
137  call symputx("&refresh_token_var",refresh_token);
138 run;
139 
140 
141 libname &libref clear;
142 filename &fref1 clear;
143 filename &fref2 clear;
144 
145 %mend;