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, source: https://github.com/sasjs/core
45 
46  <h4> SAS Macros </h4>
47  @li mp_abort.sas
48  @li mf_getplatform.sas
49  @li mf_getuniquefileref.sas
50  @li mf_getuniquelibref.sas
51  @li mf_existds.sas
52 
53 **/
54 
55 %macro mv_tokenauth(inds=mv_registerclient
56  ,outds=mv_tokenauth
57  ,client_id=someclient
58  ,client_secret=somesecret
59  ,grant_type=authorization_code
60  ,code=
61  ,user=
62  ,pass=
63  ,access_token_var=ACCESS_TOKEN
64  ,refresh_token_var=REFRESH_TOKEN
65  ,base_uri=#NOTSET#
66  );
67 %global &access_token_var &refresh_token_var;
68 
69 %local fref1 fref2 libref;
70 
71 /* test the validity of inputs */
72 %mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password)
73  ,mac=&sysmacroname
74  ,msg=%str(Invalid value for grant_type: &grant_type)
75 )
76 
77 %if %mf_existds(&inds) %then %do;
78  data _null_;
79  set &inds;
80  call symputx('client_id',client_id,'l');
81  call symputx('client_secret',client_secret,'l');
82  if not missing(auth_code) then call symputx('code',auth_code,'l');
83  run;
84 %end;
85 
86 %mp_abort(iftrue=(&grant_type=authorization_code and %str(&code)=%str())
87  ,mac=&sysmacroname
88  ,msg=%str(Authorization code required)
89 )
90 
91 %mp_abort(iftrue=(&grant_type=password and (%str(&user)=%str() or %str(&pass)=%str()))
92  ,mac=&sysmacroname
93  ,msg=%str(username / password required)
94 )
95 
96 /* prepare appropriate grant type */
97 %let fref1=%mf_getuniquefileref();
98 
99 data _null_;
100  file &fref1;
101  if "&grant_type"='authorization_code' then string=cats(
102  'grant_type=authorization_code&code=',symget('code'));
103  else string=cats('grant_type=password&username=',symget('user')
104  ,'&password=',symget(pass));
105  call symputx('grantstring',cats("'",string,"'"));
106 run;
107 /*data _null_;infile &fref1;input;put _infile_;run;*/
108 
109 /**
110  * Request access token
111  */
112 %if &base_uri=#NOTSET# %then %let base_uri=%mf_getplatform(VIYARESTAPI);
113 
114 %let fref2=%mf_getuniquefileref();
115 proc http method='POST' in=&grantstring out=&fref2
116  url="&base_uri/SASLogon/oauth/token"
117  WEBUSERNAME="&client_id"
118  WEBPASSWORD="&client_secret"
119  AUTH_BASIC;
120  headers "Accept"="application/json"
121  "Content-Type"="application/x-www-form-urlencoded";
122 run;
123 /*data _null_;infile &fref2;input;put _infile_;run;*/
124 
125 /**
126  * Extract access / refresh tokens
127  */
128 
129 %let libref=%mf_getuniquelibref();
130 libname &libref JSON fileref=&fref2;
131 
132 /* extract the tokens */
133 data &outds;
134  set &libref..root;
135  call symputx("&access_token_var",access_token);
136  call symputx("&refresh_token_var",refresh_token);
137 run;
138 
139 
140 libname &libref clear;
141 filename &fref1 clear;
142 filename &fref2 clear;
143 
144 %mend;