How can SAS Visual Analytics users change their own passwords? We are not using LDAP/Active Directory, but "internal" SAS accounts that are managed in the SAS environment.
First, I'll share the simple method: using SAS Personal Login Manager. If your end users don't have access to that tool, there is another programmatic method that you can set up -- but it's more complicated.
If you are using internal accounts for your end users (they are all sharing an OS account as the outbound login), they can change their own passwords via SAS Personal Login Manager, usually installed in the end users PCs. This gives them a simplified interface that only changes passwords stored in the SAS metadata repository.
I think I've found a solution that allows users to change passwords for internal metadata accounts (@saspw) via web interface. I've searched for an existing SAS tool or utility that could be used, but only found options to change passwords for non-internal accounts. I guess one of the reasons for that, according to Open Metadata Interface: Reference and Usage (page 170), is because "Internal logins are not intended for regular users. They are intended for metadata administrators and some service identities."
Anyway, using the SAS Java Metadata Interface documented in the reference doc mentioned above, I was able to create a Java class “setPasswd” that changes passwords for internal accounts. I have attached the code (.java.txt extension because .java is not considered a valid extension for attachements here), but I have to say that I'm not a Java programmer, and I'm sure this code can be improved, especially as it refers to error handling, constructors, and better structuring the Java class. The API methods I used require administrator privileges, so I've used sasadm@saspw internally. This custom Java class “setPasswd” can be instantiated from a SAS program within a datastep. The SAS code would look something like this (see SAS Language Reference: Concepts for additional information):
data _null_; length rc 8; dcl javaobj j ("setPasswd"); j.callIntMethod("changePasswd", "&_metaperson", "&Passwd1", rc); j.delete(); run;
Observe that this is just part of the code. Another requirement that has been shared in this thread stated that those internals accounts should be set to have their passwords expiring in 30 days or so. If the password expiration option is set, once the password is changed by an administrator, it is automatically flagged as expired to force the user to change it next time he or she logs in. This happens for example if you go to SAS Management Console as an administrator and change the password for someone else's internal account, as well as if you do so through the Java API. In order to reset that flag, you need to execute the sas code below that uses datastep metadata functions to set the attribute PasswordTimestamp (which is zero when the password is expired) with the same value as LoginTimestamp. More information can be found in the SAS Language Interfaces to Metadata:
options metauser="sasadm@saspw" metapass="99999999999999999999999999999999"; data _null_; length rc 8 id $20 type omsUri $256 logints $100; call missing(id, type, logints); omsUri = "omsobj:InternalLogin?InternalLogin[ForIdentity/Person[@Name='&_metaperson.']]"; rc=metadata_resolve(omsUri,type,id); rc=metadata_getattr(omsUri,"LoginTimestamp",logints); rc=metadata_setattr(omsUri,"PasswordTimestamp",logints); run;
I wondered if there was a method in the Java Metadata Interface that could be used to perform this step within the custom Java class and eliminate the need for the SAS code above. What inspired me to go towards this direction was this other Community post by Andreas Menrath regarding CREATE”INTERNAL ACCOUNT – PASSWORD UPDATE” in SAS 9.4.
The final step is to make this code available as a stored process that also streams a HTML form to capture the new password as a parameter to the stored process, that internally becomes the &Passwd1 macro variable. The other macro variable &_metaperson is automatically set by the stored process and contains the userid of the executing user. The following is a simplified version of the HTML interface, featuring only the key components. I have attached the complete stored process code as well:
data _null_; format infile $char256.; input; infile = resolve(_infile_); file _webout; put infile; cards4; <HTML> <HEAD> </HEAD> <BODY> <FORM ACTION="&_URL" METHOD="post"> <INPUT TYPE="HIDDEN" NAME="_program" VALUE="&_program" /> Changing password for &_metaperson (&_metauser).<br> <br> New Password<br> <INPUT TYPE=PASSWORD NAME="Passwd1" /><br> New Password (validation)<br> <INPUT TYPE=PASSWORD NAME="Passwd2" /><br> <br> <INPUT TYPE="SUBMIT" VALUE="Change Password" /><br> <br> </FORM> </BODY> </HTML> ;;;; run;
To make this stored process available to the end users in a web-based interface, you can embed it as a stored process object in a SAS Visual Analytics report:
You will need to set classpath environment variable for the SAS session that runs in the Stored Process Server. This can be done in a few different ways as documented in the SAS Language Reference: Concepts. In this example I’ve added the line below in the stored process <sas_config_dir>\Lev1\SASApp\StoredProcessServer\sasv9_usermods.cfg file. Note that I’ve copied all of the jar files I thought I’d need to my project folder, but you don’t need to do that.
In order to compile the Java program you will need to use the same version that SAS is currently using. You can find this and additional info by running the following PROC:
PROC javainfo all; run;
As a final disclaimer, I’d like highlight that I have not assessed the potential security breaches that this solution may have. If you decide to implement that in production, especial attention will be needed in order to review and improve security aspects.