Using MFA and Zowe team configuration profiles with the RSE API Node.js SDK
The RSE API Node.js SDK reads credentials directly from an existing Zowe team configuration file (zowe.config.json) by using the ProfileUtils and ProfileSession helper classes that are exported by @ibm/rse-api-for-zowe-cli. As a result, any authentication method that is configured in the team configuration file, including multi-factor authentication (MFA), is available to SDK applications without duplicating connection details in application code.
This page covers:
- Loading a session from a Zowe team configuration file
- MFA support and token-based authentication
- Short-lived MFA tokens with automatic JWT exchange
- Long-lived MFA tokens stored as a password
- Team configuration file reference for RSE profiles
Prerequisites
- Node.js 22 or later
- IBM RSE API Plug-in for Zowe CLI v6.0.0 or later
- Zowe Imperative v8.0.0 or later (peer dependency of RSE API plug-in)
- A valid Zowe team configuration file with at least one RSE profile
- Access to a z/OS system running IBM RSE API version 1.1.6 or later
For instructions on installing the plug-in and creating a team configuration file, see Setting up integrations to interact with z/OS and Example Zowe configuration setups.
Loading a session from a Zowe team configuration file
The ProfileUtils and ProfileSession classes read a Zowe team configuration file and create a fully configured imperative.Session object. This approach is recommended for SDK applications because it centralizes credential management in the Zowe team configuration file and avoids hardcoding connection details.
Using the default RSE profile
import { ProfileUtils, ProfileSession } from "@ibm/rse-api-for-zowe-cli";
// Reads ~/.zowe/zowe.config.json (or the nearest project-level config)
// and returns the profile marked as the default RSE profile.
const profile = await ProfileUtils.getDefaultRseProfile();
// Builds an imperative.Session from the loaded profile.
// If the profile has a valid, non-expired JWT, the session uses it.
// If the token is expired or absent, the session falls back to the
// stored username and password credentials.
const session = ProfileSession.getProfileSession(profile);
After a session is created, it can be used with any RSE API SDK method:
import { CheckStatus } from "@ibm/rse-api-for-zowe-cli";
const status = await CheckStatus.getRseStatus(session);
console.log(status);
Using a named RSE profile
If the team configuration file defines multiple RSE profiles, you can load a specific profile by name by using the lower-level ProfileInfo API from @zowe/imperative:
import * as imperative from "@zowe/imperative";
import { ProfileUtils, ProfileSession } from "@ibm/rse-api-for-zowe-cli";
// Retrieve the ProfileInfo object that represents the zowe.config.json
const profileInfo = await ProfileUtils.getProfileInfo();
await profileInfo.readProfilesFromDisk();
// Merge all properties for the named profile, resolving values inherited from
// parent and base profiles that are defined in the team configuration file.
const mergedArgs = profileInfo.mergeArgsForProfile(
profileInfo
.getAllProfiles("rse")
.find((p) => p.profName === "my-rse-profile")!
);
// Convert the merged arguments into a loaded profile and then create a session
const loadedProfile: imperative.IProfileLoaded = {
name: "my-rse-profile",
type: "rse",
profile: mergedArgs.knownArgs.reduce<Record<string, unknown>>(
(acc, arg) => ({ ...acc, [arg.argName]: arg.argValue }),
{}
),
failNotFound: false,
message: ""
};
const session = ProfileSession.getProfileSession(loadedProfile);
Tip: Use
ProfileUtils.getConfigLocation()to verify whichzowe.config.jsonfile is being resolved on the current system. This is useful for debugging profile resolution in CI/CD environments.
import { ProfileUtils } from "@ibm/rse-api-for-zowe-cli";
console.log(ProfileUtils.getConfigLocation());
// e.g. /home/myuser/.zowe/zowe.config.json
MFA support and token-based authentication
Zowe RSE profiles support multi-factor authentication (MFA) in two scenarios that differ based on the lifespan of the MFA token issued by your site:
| Scenario | Token lifespan | How it works |
|---|---|---|
| Long-lived MFA token | Hours | Depending on the MFA configuration, the token can be appended to the password or stored independently in the credential manager for the duration of the session. |
| Short-lived MFA token | Seconds | The token is used once for authentication and exchanged for a JWT. The JWT is then stored and used for subsequent requests. |
Both scenarios are supported for direct RSE API connections. No additional host components, such as the Zowe API Mediation Layer, are required.
Short-lived MFA tokens with automatic JWT exchange
This is the most common MFA scenario in enterprise z/OS environments. The user enters an MFA token once during login, the RSE API issues a JWT, and the JWT is stored in the team configuration file for subsequent operations.
Step 1: Configure the team configuration file
The key requirement is that autoStore is set to true in the team configuration file. When autoStore is set to true, the JWT obtained during login is stored automatically so that subsequent SDK calls can reuse it without prompts. If autoStore is set to false, the token is not stored and each operation requires a new MFA login.
Token storage depends on whether secure credential storage is enabled:
- Secure storage enabled (default): The JWT is stored in the operating system credential manager.
- Secure storage disabled: The JWT is stored as plain text in the team configuration file. This configuration is not recommended for production environments.
You do not need to declare tokenValue in the secure array. This property is managed automatically based on the credential manager configuration. The minimal RSE profile configuration is:
{
"$schema": "./zowe.schema.json",
"profiles": {
"rse": {
"type": "rse",
"properties": {
"port": 6800,
"basePath": "rseapi",
"protocol": "https"
}
},
"base": {
"type": "base",
"properties": {
"host": "myzos.example.com",
"rejectUnauthorized": true
}
}
},
"defaults": {
"rse": "rse",
"base": "base"
},
"autoStore": true
}
Step 2: Perform the MFA login
How the MFA login is performed depends on the environment in which the extension or tool runs. Choose the approach that matches the environment.
Step 2a: VS Code extension — delegate to Zowe Explorer SSO
If the code runs inside a VS Code extension, use ZoweVsCodeExtension.ssoLogin() from @zowe/zowe-explorer-api. This method delegates the entire login flow to the built-in Zowe Explorer SSO mechanism, which handles user prompting and token storage. No manual credential handling is required:
import { ZoweVsCodeExtension } from "@zowe/zowe-explorer-api";
import { ProfileUtils } from "@ibm/rse-api-for-zowe-cli";
const zoweExplorerApi = ZoweVsCodeExtension.getZoweExplorerApi("3.0.0");
if (zoweExplorerApi) {
const profilesCache = zoweExplorerApi
.getExplorerExtenderApi()
.getProfilesCache();
const zeRegister = zoweExplorerApi.getExplorerExtenderApi();
const profile = await ProfileUtils.getDefaultRseProfile();
const success = await ZoweVsCodeExtension.ssoLogin({
serviceProfile: profile, // the RSE profile needing a token
defaultTokenType: "apimlAuthenticationToken",
zeProfiles: profilesCache, // ProfilesCache instance from Zowe Explorer
zeRegister, // IApiExplorerExtender instance
preferBaseToken: false // set true to reuse a base profile token if available
});
if (!success) {
throw new Error("MFA login was not completed.");
}
}
After a successful login, Zowe Explorer stores the JWT, and ProfileSession.getProfileSession() automatically uses it on subsequent calls.
Step 2b: Node.js script — prompt and exchange with AuthLogin
If your code runs outside VS Code as a standalone Node.js script or automation tool, prompt for the user ID and MFA token and exchange them for a JWT by using AuthLogin.getToken():
import * as imperative from "@zowe/imperative";
import {
AuthLogin,
ProfileUtils,
ProfileSession
} from "@ibm/rse-api-for-zowe-cli";
import * as readline from "node:readline/promises";
async function loginWithMfa(): Promise<imperative.Session> {
const profile = await ProfileUtils.getDefaultRseProfile();
const session = ProfileSession.getProfileSession(profile);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// Prompt for any credentials that are not already defined in the profile.
if (!session.ISession.user) {
session.ISession.user = await rl.question("Enter your user ID: ");
}
const mfaToken = await rl.question("Enter your MFA token: ");
rl.close();
// Use the MFA token as the password for the login request.
session.ISession.password = mfaToken;
// Exchange the MFA token for a JWT.
// The SDK updates session.ISession.tokenValue in place and, because
// autoStore is set to true in the team configuration file, also stores the JWT in the
// credential manager.
await AuthLogin.getToken(
session,
profile.name!,
profile.profile as imperative.IProfile,
/*autoRefreshToken=*/ false // MFA tokens cannot be auto-refreshed
);
return session;
}
const session = await loginWithMfa();
Step 2c: Zowe CLI plug-in — use ConnectionPropsForSessCfg.addPropsOrPrompt
If the code runs as a Zowe CLI plug-in command handler, imperative.ConnectionPropsForSessCfg.addPropsOrPrompt() provides a convenient alternative. It resolves session properties from the command arguments and prompts the user only for values that are still missing. No manual prompting logic is required.
The options object controls several important behaviors:
doPrompting— Enables interactive prompting for missing properties, such as user ID and password (the MFA token).autoStore— Controls whether the resulting token is persisted to the team configuration file. Set this property tofalsewhen handling alogincommand, because the login handler is responsible for storing the token.defaultTokenType— Specifies the token type to request. Use'jwtToken'for direct RSE API connections.serviceDescription— Used in prompts and credential manager entries to identify the associated service.
import * as imperative from "@zowe/imperative";
import { ProfileUtils, ProfileSession } from "@ibm/rse-api-for-zowe-cli";
// Inside a Zowe CLI plug-in ICommandHandler.process() implementation:
const isession = ProfileSession.getProfileSession(
await ProfileUtils.getDefaultRseProfile()
).ISession;
const sessCfgWithCreds =
await imperative.ConnectionPropsForSessCfg.addPropsOrPrompt<imperative.ISession>(
isession,
this.params.arguments,
{
parms: this.params,
doPrompting: true,
autoStore: this.params?.definition?.name !== "login",
defaultTokenType: "jwtToken",
serviceDescription: "RSEAPI"
}
);
return new imperative.Session(sessCfgWithCreds);
Step 3: Use the session for subsequent requests
After login, the JWT is stored in the session and credential manager. Load the profile again at the start of subsequent operations, and ProfileSession.getProfileSession() automatically uses the stored JWT:
import { ProfileUtils, ProfileSession, List } from "@ibm/rse-api-for-zowe-cli";
// On subsequent calls, the stored JWT is used automatically.
// No MFA prompt is required until the JWT expires.
const profile = await ProfileUtils.getDefaultRseProfile();
const session = ProfileSession.getProfileSession(profile);
const response = await List.allMembers(session, "MY.PDS");
console.log(response.apiResponse.items.map((i: any) => i.memberName));
Logging out and retiring the JWT
When you are finished with the session, retire the JWT by using AuthLogout:
import {
AuthLogout,
ProfileUtils,
ProfileSession
} from "@ibm/rse-api-for-zowe-cli";
const profile = await ProfileUtils.getDefaultRseProfile();
const session = ProfileSession.getProfileSession(profile);
await AuthLogout.logout(session);
// The JWT is invalidated on the server and removed from the credential manager.
Long-lived MFA tokens stored as a password
Some sites issue MFA tokens that remain valid for an extended period, such as several hours or the duration of a z/OS logon session. In these environments, the combined credential (a password with the MFA token appended) or, depending on the MFA configuration, the MFA token alone can be passed directly as the password in the session:
import * as imperative from "@zowe/imperative";
import { CheckStatus } from "@ibm/rse-api-for-zowe-cli";
const session = new imperative.Session({
hostname: "myzos.example.com",
port: 6800,
user: "MYUSERID",
password: "mypassword:123456", // combined password:mfaToken
protocol: "https",
type: "basic"
});
const status = await CheckStatus.getRseStatus(session);
console.log(status);
Note: Hard-coding credentials, including combined MFA credentials, is not recommended for production code. Use Zowe secure storage or environment variables, and load credentials at run time. For cloud development environments, see Using environment variables for authentication in Zowe Explorer.
Team configuration file reference for RSE profiles
The following table lists the properties that are relevant to RSE profiles and authentication in the team configuration file.
| Property | Location | Description |
|---|---|---|
host | rse.properties or base.properties | Hostname or IP address of the RSE API server. |
port | rse.properties | Port number of the RSE API server (6800 is the default). Confirm the port number with the system administrator. |
basePath | rse.properties | URL base path of the RSE API server. The default value is rseapi. |
protocol | rse.properties | Must be https. |
rejectUnauthorized | rse.properties or base.properties | Set to true for production environments. Set to false only when connecting to a server with a self-signed certificate in a trusted development environment. |
user | rse.properties or base.properties | z/OS user ID. Stored in the operating system credential manager when included in the secure array. |
password | rse.properties or base.properties | z/OS password, passphrase, or combined password:mfaToken value for long-lived MFA tokens. Stored securely when listed in the secure array. |
tokenValue | rse.properties | JWT obtained after successful authentication. Stored securely when listed in the secure array. Set by AuthLogin.getToken() and cleared by AuthLogout.logout(). |
autoStore | Top-level | When true, credential values are persisted to the credential manager automatically after login. Required for JWT-based and MFA workflows. |
For complete configuration examples, see Example Zowe configuration setups.