Friday, June 20, 2025

🔐 How to Decode a JWT Token in PeopleCode Using Java (No Extra Libraries)

Use Case: Securely decode and inspect a JWT (JSON Web Token) in PeopleSoft using native Java classes, without relying on external libraries or PeopleCode JSON parsers.

 Why Decode a JWT in PeopleCode?

In modern PeopleSoft integrations — especially with OAuth 2.0, SSO (Single Sign-On), and Microsoft Azure AD authentication — JWTs (JSON Web Tokens) are used to pass identity and authorization information. For example:

  • A REST API request might carry a JWT in the Authorization header.

  • You might need to extract user identity (upn, email, roles) from the token.

  • You want to verify what claims (data) were issued in the JWT — without calling external tools.


🛠️ The Challenge

PeopleCode doesn't have built-in JWT libraries or even a native Base64 URL decoder. But with a little help from standard Java classes (available in all PeopleTools environments), we can manually decode and read the JWT payload.


✅ Use Case

Let’s say:

  • You have an OAuth-secured API call hitting PeopleSoft.

  • You’re intercepting the JWT from the %Request.GetHeader("Authorization") PeopleCode method.

  • You want to read the user identity inside the token for auditing or mapping purposes.


🔧 Sample PeopleCode: Decode JWT Payload (Pure Java, No Parser Yet)

peoplecode
Local string &jwt, &payload, &decodedPayload; Local array of string &parts; Local number &mod4; Local JavaObject &decoder, &payloadBytes, &decodedBytes, &decodedString; /* Step 1: Build the JWT from pieces (used here for testing only) */ &part1 = ".."; &part2 = ".."; &part3 = ".."; &part4 = ".."; &part5 = ".."; &jwt = &part1 | &part2 | &part3 | &part4 | &part5; /* Step 2: Split the JWT */ &parts = Split(&jwt, "."); If &parts.Len >= 2 Then /* Step 3: Get payload part */ &payload = &parts[2]; /* Step 4: Normalize Base64URL */ &payload = Substitute(&payload, "-", "+"); &payload = Substitute(&payload, "_", "/"); /* Step 5: Add padding */ &mod4 = Mod(Len(&payload), 4); If &mod4 = 2 Then &payload = &payload | "=="; Else If &mod4 = 3 Then &payload = &payload | "="; End-If; End-If; /* Step 6: Base64 decode using Java */ &decoder = GetJavaClass("java.util.Base64").getDecoder(); &payloadBytes = CreateJavaObject("java.lang.String", &payload).getBytes(); &decodedBytes = &decoder.decode(&payloadBytes); &decodedString = CreateJavaObject("java.lang.String", &decodedBytes); &decodedPayload = &decodedString.toString(); /* Step 7: Display decoded JSON payload */ WinMessage("Decoded JWT Payload: " | &decodedPayload); Else WinMessage("Invalid JWT format."); End-If;

Friday, January 17, 2025

How to Convert CSV to XLSX in PeopleSoft Using the PSSpreadsheet Class

 Working with large datasets often requires transitioning data between formats. In PeopleSoft, you can efficiently convert a CSV file to an XLSX file using the PSSpreadsheet class. This guide will walk you through how to automate this conversion with a simple PeopleCode program.

Why Convert CSV to XLSX?

  • Better Data Handling: Excel handles large datasets more effectively than CSV, especially when working with formulas, charts, and formatting.

  • Improved Readability: XLSX allows for better organization with multiple sheets and styling options.

  • Integration with PeopleSoft: The PSSpreadsheet class makes it easy to programmatically generate Excel files.

Prerequisites

  • Access to PeopleSoft Application Designer

  • Basic knowledge of PeopleCode

  • Required permissions to run App Engine programs

Step-by-Step Implementation

1. Create an App Engine Program

Open PeopleSoft Application Designer and create a new App Engine program. Add a PeopleCode action where the conversion logic will be placed.

2. PeopleCode to Convert CSV to XLSX

 Run the App Engine Program

  1. Save and register the App Engine.

  2. Run it through the Process Scheduler or manually in PeopleSoft. Do not run in two tier app designer.

  3. The Excel file (Output.xlsx) will be generated in the defined directory.


/* Set the file paths */
/* Hardcoded Input CSV File Path /
&csvFileName = "<Path_to_dir>test_csv.csv"; /
Replace with actual CSV path */ /* Set Output Excel File Name */
&outFileName = "<Path_to_dir>Output.xlsx";/ *Replace with actual xlsx path */ /* Create Spreadsheet using PSSpreadsheet class */
Local object &ss;
&ss = CreateObject("PSSpreadsheet");
&ss.Open(&outFileName, True); /* Open the CSV File for Reading */
Local File &file;
&file = GetFile(&csvFileName, "R", "A", %FilePath_Absolute); If &file.IsOpen Then Local string &line; Local number &row = 1; Local array of string &columns; /* Read each line from the CSV */ While &file.ReadLine(&line) /* Split the line by comma (CSV) */ &columns = Split(&line, ","); /* Write data to Excel */ Local number &col; For &col = 1 To &columns.Len &ss.SetCellString(&row, &col, &columns [&col]); End-For; &row = &row + 1; End-While; /* Close the file */ &file.Close(); End-If; /* Save the Excel file */ &ss.Save();

Wednesday, March 1, 2023

Peoplesoft Downtime Notification in Header

  Often we recycle Non prod server or even prod server during business hours. ideally we send email to users but not all the time users will see email as they continue to work in PeopleSoft. so thought there should be a interactive way to notify the users about downtime or maintenance etc.

Peopelsoft provides push notification but it does not give the option to broadcast for performance reasons.

Here is the simple approach to broadcast any message. for example i need to shutdown one of my production server at specific time so now i am going to push this message



1. Navigate to Peopletools - Portal - Branding - Define Branding Headers and Footers



2.Bring up your header in this case fluid.

3.Navigate to company info and click on additional options



4.Enable Company banner area.

5.Add below marquee text so that it will scroll at the top and its eye catchy users can read and save their work.

<marquee direction="left" height="20px" width="100%"> System Will Go down in 10 minutes for Maintenance.We will be back @ 12 PM EST. Sorry for the inconvenience. </marquee>


Output/Result.

System Will Go down in 10 minutes for Maintenance. We will be back @ 12 PM EST. Sorry for the inconvenience.

 


Beauty of this approach is no cache clear is required . PeopleSoft brilliantly uses rowset cache method for company info which works well.

Monday, August 3, 2020

How to Disable TLS1.0/1.1 in Peoplesoft

Recent times all the organization had started disabling the tls 1.0/1.1 protocol across thirer network.


here is the extensive list on various places you need to disable in peoplesoft component.


1. Webserver - Under setenv append below parameter.

 

SET JAVA_OPTIONS_WINXX=-server -Xms512m -Xmx512m -XX:MaxPermSize=128m -Dtoplink.xml.platform=oracle.toplink.platform.xml.jaxp.JAXPPlatform -Dweblogic.security.SSL.minimumProtocolVersion=TLSv1.2

 

2. Appserver/Prcs Server - under psappsrv.cfg & psprcs.cfg file append below parameter.

 

JavaVM Options=-Dxdo.ConfigFile=%PS_HOME%/appserv/xdo.cfg -Xms32m -Xmx128m -Dhttps.protocols=TLSv1.2

 

3. Elastic Search- Update below in $JAVA_HOME/lib/security/java.security (Doc ID 2470444.1)

 

jdk.tls.disabledAlgorithms=SSLv3, TLSv1.0,TLSv1.1, RC4, MD5withRSA, DH keySize < 1024, EC keySize < 224, DES40_CBC, RC4_40, 3DES_EDE_CBC

 

4. Ren Server - Update psrenconfig.txt with below values. (Doc ID 2536363.1))

 

# Restrict the REN server to a particular version or versions of SSL

# allowed values are tlsv1, tlsv1_1, tlsv1_2

ns_param ServerProtocols tls1_2

ns_param SockServerProtocols tls1_2

ns_param SockClientProtocols tls1_2

 

5. LDAP - For peopletools 8.54.20 or above its already TLS1.2 is enabled by default.

 

final String protocol = vendor.toLowerCase().contains("ibm") ? "SSL_TLSv2" : "TLSv1.2";

final SSLContext sslcontext = SSLContext.getInstance(protocol);

 

6. SES - Update below.

 

In <mw_home>/user_projects/domains/search_domain/bin/setDomainEnv.sh, set:

JAVA_OPTIONS="${JAVA_OPTIONS} -Dweblogic.security.SSL.minimumProtocolVersion=TLSv1.2 -Djdk.tls.client.protocols=TLSv1.2"

 

Testing:

1. Webserver - Disable TLS 1.0/TLS1.1 in browser and try accessing your PIA site or if your site is accessible in chrome it is enforced to TLSv1.2. Chrome disable TLS1.0/1.1 long back.

2. App Server - If you use https gateway try loading it . it should succesully load the connectors.

    Prcs  Server  - In case if your report node is configured to use https protocol. then try running sample report and this should succesfully post your report to web server.

3. ES Server - Here we are just disabling as far as ES ping succesful then you are good.

4. Ren Server - Follow point #1 to run the ren server reports in browser.

5. LDAP -Try pinging LDAP configure directory.

6. SES - Follow Point #3.

Wednesday, July 22, 2020

Peoplesoft Kerberos SSO Extended Logging

Kerberos is moving away from peoplesoft as of PT 8.57. Until 8.56 Oracle used to deliver the SDK and later on they removed the SDK from Tools package.

Surprisingly oracle does delivers the source code for customers to make use of this and use kerberos as an SSO.

You can find the sorce code from below location

$PS_HOME/sdk/desktopsso/src/com/peoplesoft/pt/desktopsso/kerberos

KerberosSSOFilter.java  ===> Will be used in webserver for requesting token.
KerberosSSOValidator.java ===> Will be used for app server validation.


Kerberos is a such a nice and strong SSO solution so i would keep using SSO but it does lacking the logging feature.

Means if there is any issue you cannot simply troubleshoot as error message just says below


 <BEA-000000> <KerberosSSOFilter: Received invalid token.>

Error seems to be generic. So i thought we can add few more logging capability in java class and recompile it.

Add below line of code right after line #142.

142             catch (GSSException e) {
143                 this.verbPrint("Received invalid token.");
144                 this.verbPrint(e.getMajorString());
145                 this.verbPrint(e.getMinorString());
146                 this.verbPrint(e.getMessage());
147                 this.verbPrint(e.toString());
148                 System.out.println("Major Code: " + String.valueOf(e.getMajor()));
149                 System.out.println("Minor Code: " + String.valueOf(e.getMinor()));


Try compiling it using JDK (please do not use JRE)

$PS_CFG_HOME/webserv/<domain_name>/bin/. ./setEnv.sh
export CLASSPATH=$CLASSPATH:$PC_CFG_HOME/webserv/<domain_name>/applications/peoplesoft/PORTAL.war/WEB-INF/classes
$JDK_HOME/javac KerberosSSOFilter.java 


In case if you get below error while compiling.

KerberosSSOFilter.java:324: error: getHeaderNames() in KerberosSSOFilter.KerberosAuthWrapper cannot implement getHeaderNames() in HttpServletRequest public Enumeration getHeaderNames() { ^ return type Enumeration is not compatible with Enumeration

Please get the line # and change the ? with string like below.


180         @Override
181         public Enumeration<String> getHeaders(final String name) {
182             if (name.equals("KRB_USER")) {
183                 final Vector<String> values = new Vector<String>();
184                 values.add(this.principalName);
185                 return values.elements();
186             }
187             final HttpServletRequest req = (HttpServletRequest)this.getRequest();
188             return req.getHeaders(name);


Now the actual error message will be logeed in your PIA_stdout.log along with received invalid token.

<BEA-000000> <KerberosSSOFilter: Received invalid token.>
<BEA-000000> <KerberosSSOFilter: Failure unspecified at GSS-API level>
<BEA-000000> <KerberosSSOFilter: Invalid argument (400) - Cannot find key of appropriate type to decrypt
 AP REP - AES256 CTS mode with HMAC SHA1-96>
<BEA-000000> <KerberosSSOFilter: Failure unspecified at GSS-API level (Mechanism level: Invalid argument
 (400) - Cannot find key of appropriate type to decrypt AP REP - AES256 CTS mode with HMAC SHA1-96)>
<BEA-000000> <KerberosSSOFilter: GSSException: Failure unspecified at GSS-API level (Mechanism level: In
valid argument (400) - Cannot find key of appropriate type to decrypt AP REP - AES256 CTS mode with HMAC SHA1-96)>
<BEA-000000> <Major Code: 11>
<BEA-000000> <Minor Code: -1>


You can pass on this error message to respective team who is responsible for generating keytab.





Wednesday, July 31, 2019

User Profile Emulation in PeopleSoft

We used to simulate the user issue in non prod by changing the password for respective username and login to replicate the issue.Its always a security concern and there is no track of it.

I have seen other ERP application does gives this emulate  as different user functionality without touching their security. But peoplesoft does not give such feature for user emulation.

i have created an Idea in oracle community to get this future in peopletools. hope this will be accommodated in future release. Please do vote .

https://community.oracle.com/ideas/23725

In the interim i came up with below idea.with this approach you do not need to change end user password and also it keeps the track of individual user who is emulating as other user.

So below blog will explain you on how you will emulate as different user.

1. Create new site called simulate in existing weblogic domain.

for example : 

Existing Site Name : PSDEV
New Site Name  : SIMULATE

2. Add below html in your original site signin.html. (PSDEV)


<a href="https://velu.peoplesoft.com/psp/simulate/?cmd=login">Impersonate User</a>

3. Add below html in your new site signin.html (SIMULATE)









<div>
               <span class="ps_label-show" id="ptLabelUserid"><label for="imuserid"><%=1333%></label></span>
             </div>
             <div class="ps_box-control">
               <input type="text" id="imuserid" name="imuserid" value="<%=IMUSERID%>" title="<%=1333%>">
           </div>

4. Open your FUNCLIB_LDAP record and goto LDAPAUTH field peoplecode.

Create new function called IMPERSONATE as below.









Function impersonate();
   &signonusername = %SignonUserId;
   &userName = %Request.GetParameter("IMUSERID");
   &ipaddress = %Request.GetHeader("X-FORWARDED-FOR");
   SQLExec("select roleuser from psroleuser where rolename='PeopleSoft Administrator' and roleuser=:1", &signonusername, &roleuser);
   If &userName = "" Then
      SetAuthenticationResult( True, Upper(&signonusername), "", False);
   Else
      If &roleuser = "" Or
            &userName = "PSADMIN" Or
            &userName = "PSAPPS" Or
            &userName = "PTWEBSERVER" Then
         SetAuthenticationResult( False, &userID, "You are not authorized to do Impersonation");
      Else
         SQLExec("INSERT INTO PS_IMPERSONATE VALUES (:1,:2,:3,:4)", &signonusername, &userName, &ipaddress, %Datetime);
         SetAuthenticationResult( True, Upper(&userName), "", False);
      End-If;
   End-If;
   
End-Function;

5. Create a new record with below field to keep a track of who is logging in.






Make sure you build the record

6.Add LDAP_AUTH peoplecode in signon peoplecode as below.










Bounce your app server by clearing cache.

Tetsing:

1. Open your exiting PIA. You will see a Hyperlink called Impersonate User.














2. Click on impersonate user. It will take you to your newly created SITE called simulate.

















Now provide your username/password and the username you want to login as.(in Impersonate user as)


















You can see it logged in as user id which you put in.















3.You can query the table select * from PS_IMPERSONATE to check if the values are captured. this will help you for audit purpose.

Points to note:

1. I have hardcoded Peoplesoft Administrator role in peoplcode. So if you any user want to use this functionality they should have Peoplesoft Administrator Role else it will throw below error.










2. Also you may need to use peoplesoft password to login , if you use LDAP password it may fail. I will update the post once i enhance my peoplecode to make it work with LDAP password

Peopletools 8.56.18
DB 12C


NOTE: I would recommend only to use it in NON-PROD .. never move this code to production .

I just did this as for learning purpose. Implement this on your sole responsibility.

Thursday, July 11, 2019

Weblogic Console password reset

I have tried so many ways and concluded that  We don’t have any procedure to override the existing console password. So, in this blog w

Monday, April 15, 2019

Find Menu Navigation in Peoplesoft

Below are few ways to find Menu Navigation

1. SQL to find Menu navigation.


SELECT A.PORTAL_LABEL || ' --> ' || B.PORTAL_LABEL || ' --> '  || C.PORTAL_LABEL || ' --> '  ||  D.PORTAL_LABEL Navigation FROM PSPRSMDEFN D, PSPRSMDEFN C, PSPRSMDEFN B
, PSPRSMDEFN A WHERE D.PORTAL_PRNTOBJNAME = C.PORTAL_OBJNAME AND C.PORTAL_PRNTOBJNAME = B.PORTAL_OBJNAME AND B.PORTAL_PRNTOBJNAME = A.PORTAL_OBJNAME AND D.PORTAL_NAME = C.PORTAL_NAME AND C.PORTAL_NAME = B.PORTAL_NAME AND B.PORTAL_NAME = A.PORTAL_NAME
AND D.PORTAL_URI_SEG2 = <provide Component name>;

2. Use enterprise component to find object navigation as below. Navigate Menu --> Enterprise Components --> Find Object Navigation..

Also you can refer below doc .

Sunday, April 14, 2019

PeopleSoft Fluid Approval Form Instruction Page -Rich Text Editor



In classic Approval page form builder we do see an option for Rich Text editing as below. But when you look at the fluid page RTE is not enabled . This is due to the limitation of FLUID page as it does not support RTE (E-FLUID : Is RTE(Rich Text Editor) Field Supported In Fluid Pages ? (Doc ID 2108005.1)

So as a workaround you can try to embed HTML tag as shown below in FLUID form builder instructions page.
 
i have simple html tag as shown below . It works well.



You can also try in HTML editor and simply copy paste with HTML tags.





Monday, March 27, 2017

Concurrent Users in Peoplesoft

This article is all about counting number of concurrent users connected to People soft.

We all know each and every login will make an entry in PSACCESSLOG table with Login & Logout Date and Time.But its not that accurate , because when the user closed the session without signing out then logout time will never be captured.

So to over come this issue I got an idea to get the session details from Web server as this will give you the live data.

Step:1 Create the script called Session.py as mentioned below

#File Name : 'Session.py'
# Author : Velu
import sys
import datetime
now = datetime.datetime.now()
filecsv = open("$PS_HOME/webserv/psofthr/applications/peoplesoft/PORTAL.war/session.csv", "a")
file = open("$PS_HOME/webserv/psofthr/applications/peoplesoft/PORTAL.war/session.log", "a")
print >>file, "Current date and time:",now.strftime("%Y-%m-%d %H:%M")
connect('system','Password1!','t3://WEBSERVERHOST:PORT')
serverRuntime()
cd ('ApplicationRuntimes/peoplesoft/ComponentRuntimes/PIA_')
currentsession1= get('OpenSessionsCurrentCount')
print >>file, "=========================================="
print >>file, "Number of session in Peoplesoft Webserver  :" ,currentsession1

Step:2 Create a script called sessionmonitor.ksh as mentioned below.

#File Name :'sessionmonitor.ksh'
#Author : Velu
#!/bin/ksh
cd $WL_HOME/oracle_common/common/bin
./config.sh
cd $WL_HOME/oracle_common/common/bin
./wlst.sh /global/site/vendor/psofthr/scripts/sessionmonitor.py

Step 3: Schedule a sessionmonitor.ksh for every 5 minutes in cron .

Step 4: Now access the below URL to get the live data.

       http:/webserverhost:port/session.log


Step 5: As we are generating the output in CSV format as well ,so you can get the graphical way to get the concurrent users. I used Qlik sense tool and this tool will accept http url and here is the snapshot.

http://webserverhost:port/session.csv



Appendix:

  You can also get more information from WLST . if you would like to get the user details follow the below command.




Hope this helps!!!!

Please comment for any issue/Questions.





Monday, November 21, 2016




PeopleSoft Elastic Search Installation

This video demonstrates the Elastic Search installation DPK for PeopleSoft. Below is the environment details.




People tools 8.55.11
HCM 9.2 Image 19
Tuxedo 12.1.3 Patch 040
Weblogic 12.1.3
Oracle Database 12.1.0.2

Thanks for Watching.
Please comment for any issues.

🔐 How to Decode a JWT Token in PeopleCode Using Java (No Extra Libraries)

Use Case: Securely decode and inspect a JWT (JSON Web Token) in PeopleSoft using native Java classes, without relying on external libraries...