@sap/cds-dk
Version:
Command line client and development toolkit for the SAP Cloud Application Programming Model
185 lines (131 loc) • 7.34 kB
JavaScript
module.exports = Object.assign(login, {
options: ['--subdomain', '--directory', '--passcode', '--user', '--client', '--mtls'],
shortcuts: ['-s', '-d', '-p', '-u', '-c', '-m'],
flags: ['--plain', '--save-refresh-token'],
get help() {
const config = require('../lib/mtx/settings_manager').SettingsManager.config
return `
# SYNOPSIS
*cds login* [ <app-url> ]
Simplifies usage of multitenancy-related commands (e.g. *cds subscribe* and
*cds push*) by providing them with automatic authentication: fetches and
saves Access Tokens and provides relevant tokens to those commands.
Alternatively saves username for apps running locally.
Saves further settings for the current project (<app-url>,
<tenant-subdomain>, and URLs for passcodes and tokens).
*Multiple targets*
When re-running this command with different app URLs and subdomains,
previous logins are not affected, allowing simultaneous logins to different
API endpoints on SAP Business Technology Platform, Cloud Foundry
environment. *cds pull* and *cds push* will be authenticated according
to the given target.
If the Cloud-Foundry command-line client is installed, the SaaS-app URL
<app-url> may be omitted. In that case, suitable apps from the org and space
you're currently logged in to will be presented to determine <app-url>.
In case <app-url> does not start with a schema, 'https://' is assumed.
*Token Expiration*
If a Refresh Token has been saved with the original token (see option
--save-refresh-token) and the original token has expired, it will be
automatically renewed.
*Storing Authentication Data*
Authentication data for all logins is saved by <app-url> and
<tenant-subdomain> in the desktop keyring (${(config.keyringDesignation)} on
your platform) or, if requested, in config file ${config.paths.auth}.
To make use of keyring storage, the 'keytar' Node.js module must be
installed. A corresponding hint will be given in case the module is not
found.
Project settings are saved by project directory in config file
${config.paths.settings}.
Note that local storage of authentication data incurs a certain security
risk: a malicious locally-running application might be able to perform any
action with the SaaS app that you are authorized for with respect to your
tenant.
# OPTIONS
*-s* | *--subdomain* <tenant-subdomain>
The subdomain to log in to. By default, it's determined from project
settings. If no such setting is saved, the CF client is invoked to
determine the respective subdomain.
*-d* | *--directory* <extension-project-directory>
The extension-project folder (relevant for loading and saving settings).
If omitted, the current working directory will be used.
*-p* | *--passcode* <passcode>
Tenant-specific passcode for authentication.
*-u* | *--user* <name>[:[<password>]]
Username and optionally password for authentication with Basic Auth in
test scenarios.
When typing the colon but omitting <password>, the password is assumed
empty. When omitting both, password will be queried interactively.
For security reasons, username will only be saved for app URLs that look
like localhost. In this case, the username will be associated with the
project folder, not with the (potentially ambiguous) URL.
An empty password will be saved under the same conditions as a username.
Non-empty passwords will never be saved.
Note: Productive secrets should not be specified on a command line,
since this might expose them to unauthorized users on the same machine!
*-c* | *--client* <clientid>[:<clientsecret>]
Client Credentials (Client ID and optionally Client Secret) for
authentication. If omitted, Client Secret will be queried interactively.
Obtain the Client Credentials from the UAA binding of MTXS.
Client Credentials will not be saved, only the resulting token.
Note: Productive secrets should not be specified on a command line,
since this might expose them to unauthorized users on the same machine!
*-m* | *--mtls* <clientid>[:<key>]
Client Credentials (Client ID and optionally Client-Certificate Private
Key in Base64 encoding) for authentication. If omitted, Private Key will
be queried interactively (avoid newline characters when pasting it).
Obtain the Client Credentials from the UAA binding of MTXS.
Client Credentials will not be saved, only the resulting token.
Note: Productive secrets should not be specified on a command line,
since this might expose them to unauthorized users on the same machine!
*--save-refresh-token*
Also store the Refresh Token (if provided) for automatic renewal of the
Access Token upon expiration.
*--plain*
Instead of saving authentication data for this login to the desktop
keyring, use plain-text storage, e.g. if you have not installed the
'keytar' module.
Note that this is not recommended as it decreases the level of security:
at least applications running as the current user can read the
plain-text file, whereas the keyring (depending on the platform) can be
locked and unlocked on owner request and may hide data saved by this
command from other applications you run.
Be aware that on SAP Business Application Studio, --plain is enforced,
since keyring functionality is not supported. However, the underlying
storage is encrypted.
During login, potential pre-existing authentication data for the same
target is deleted from the other, non-selected storage. This allows
migrating authentication data from one storage to the other by running
the present command without a passcode.
# SEE ALSO
Supported commands: *cds subscribe*, *cds upgrade*, *cds pull*, *cds push*,
and *cds unsubscribe*.
*cds logout* to remove any authentication data.
https://cap.cloud.sap/docs/guides/extensibility/customization#mock-users for
information on suitable mock users.
`}});
async function login ([url], options = {}) {
const [username, password] = options.user?.split(':') ?? [];
delete options.user;
if (options.client) {
const [clientid, clientsecret] = options.client.split(':');
delete options.client;
Object.assign(options, { clientid, clientsecret });
} else if (options.mtls) {
const [clientid, key = 'ask'] = options.mtls.split(':');
delete options.mtls;
Object.assign(options, { clientid, key });
}
Object.assign(options, {
url,
username,
password,
tokenStorage: options.plain ? 'plain' : 'keyring',
renewLogin: true,
saveData: true,
saveRefreshToken: options['save-refresh-token'] ?? false
});
delete options.plain;
delete options['save-refresh-token'];
await require('../lib/mtx/auth_manager').login(options);
}
/* eslint no-console: off */