Install M7 Identity SDK for CLI and background processes
The stable releases are token-php 0.1.2 and cli-php 0.1.1. The CLI requires
token-php >=0.1.2 <0.2.0 for client credentials, device code,
refresh-package exchange, ACK, ensure, and authenticated resource requests.
For the complete operator processes, use the public CLI subject guide, which covers client credentials, device authorization, managed ensure, ACK, and authenticated requests beside this installation page.
Download token-php 0.1.2 as its ZIP,
SHA-256 checksum,
and release manifest.
Download cli-php 0.1.1 as its ZIP,
SHA-256 checksum,
and release manifest.
Verify and extract the CLI
Keep each ZIP with its .sha256 and .manifest.json sidecars. Verify both
archives before extraction:
shasum -a 256 -c m7-identity-token-php-0.1.2.zip.sha256
shasum -a 256 -c m7-identity-cli-php-0.1.1.zip.sha256
unzip m7-identity-token-php-0.1.2.zip -d ./vendor
unzip m7-identity-cli-php-0.1.1.zip -d ./vendor
Point the CLI at the separately installed token package:
export M7_IDENTITY_TOKEN_ROOT="$PWD/vendor/m7-identity-token-php-0.1.2"
Use the client-credentials CLI
Confirm the packaged command and dependency load:
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity --version
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity client-credentials --help
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity request --help
Start the controlling-terminal prompt flow with:
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity client-credentials --interactive
To use the protected keychain, select an existing machine app. Its profile
defaults to default; a successful complete response is stored before stdout:
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity client-credentials \
--app user.m7.org-cc \
--interactive
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity token status \
--app user.m7.org-cc \
--grant client-credentials
The second command prints metadata, never the token. Calls without --app
remain stateless.
Or configure an unattended call. The secret file must not be a symlink and must grant no group or other permissions:
chmod 0600 /run/secrets/m7-client-secret
export M7_CLIENT_CREDENTIALS_CLIENT_ID='YOUR_REGISTERED_CLIENT_ID'
export M7_CLIENT_CREDENTIALS_CLIENT_SECRET_FILE='/run/secrets/m7-client-secret'
export M7_CLIENT_CREDENTIALS_AUD='https://api.user.m7.org/'
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity client-credentials --output token
Any defined M7_CLIENT_CREDENTIALS_* value overrides its matching CLI option.
An empty defined value also overrides the option and may fail validation; the
command never silently falls back around deployment configuration.
Create and run a managed public device client from the same installation:
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity app upsert user.m7.org-device \
--client-id YOUR_REGISTERED_DEVICE_CLIENT_ID \
--type native \
--authority consumer
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity profile upsert \
--app user.m7.org-device \
--grant device-code \
--config-json '{"auth_method":"none","aud":["https://user.m7.org"],"scope":"openid profile offline_access","refresh_mode":"strict_rotation"}'
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity device-code \
--app user.m7.org-device
The upserts make this setup block repeatable. They replace the editable app and profile definitions rather than merging stale fields, while retaining stored passwords and complete token history.
The raw stateless form is also available:
export M7_DEVICE_CODE_AUTH_METHOD='none'
export M7_DEVICE_CODE_CLIENT_ID='YOUR_REGISTERED_DEVICE_CLIENT_ID'
export M7_DEVICE_CODE_SCOPE='openid profile offline_access'
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity device-code
Interactive configuration is also available:
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity device-code --interactive
The browser approval page owns account authentication. Do not enter an M7 password into the CLI or store it beside the device code.
To rotate the managed bundle in place:
M7_EXCHANGE_REFRESH_MODE=strict_rotation \
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity exchange \
--app user.m7.org-device
To exchange a stateless protected bundle returned by a raw device flow:
chmod 0600 /run/secrets/m7-refresh-bundle.json
export M7_EXCHANGE_AUTH_METHOD='none'
export M7_EXCHANGE_CLIENT_ID='YOUR_REGISTERED_DEVICE_CLIENT_ID'
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity exchange \
--bundle-file /run/secrets/m7-refresh-bundle.json
The raw output is a rotated replacement package. It does not rewrite its input, so persist the entire output before retiring the preceding bundle. The separate store can import a protected complete bundle explicitly:
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity token import \
--app YOUR_LOCAL_APP \
--grant device-code \
--file /run/secrets/m7-refresh-bundle.json
Omitting --profile selects default; app and grant are always explicit.
For managed two-phase activation, exchange stores pending and ACK promotes the exact generation after authority success:
M7_EXCHANGE_REFRESH_MODE=ack \
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity exchange \
--app user.m7.org-device
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity ack \
--app user.m7.org-device
On failure, pending storage is retained. Use --id GENERATION if several
pending generations exist.
For a fault-tolerant ACK lifecycle, set
M7_EXCHANGE_REFRESH_MODE=ack_supersede_pending and run exchange --app user.m7.org-device; then run ack --app user.m7.org-device. With no pending
state it starts normally from active. If a pending child already exists,
Identity disables it and issues the newest child while the predecessor stays
active until ACK. A locally retained pending generation is removed only after
its successor is stored. The protected-file forms remain available for
stateless/manual operation.
Call a protected API with a managed token:
./vendor/m7-identity-cli-php-0.1.1/bin/m7-identity request \
--app user.m7.org-device \
--url https://api.user.m7.org/api/v2/session/me \
--response json \
--query include=groups
With --app, the command reuses a fresh token or ensures and stores a
replacement before sending. Use --minimum-ttl and --refresh-mode to control
managed preflight; native profiles without a configured mode default to
ack_supersede_pending. Without --method, requests use GET unless JSON data
is supplied, which selects POST. The command also accepts --bundle PATH,
--bundle-stdin, protected manual token input, and separate fingerprint or
fresh DPoP proof input; those explicit credential sources are never refreshed
or stored. It does not blindly retry an API 401.
With --response json, an incorrectly typed or malformed 2xx response also
fails while retaining its original body for diagnosis.
The remainder of this page describes the independently published library artifact for PHP programs and background workers.
1. Check the library runtime
Use PHP 8.1 or newer with OpenSSL:
php -v
php -m | grep -E '^(curl|openssl)$'
OpenSSL is required. cURL is recommended for token acquisition, authenticated resource requests, live certificate retrieval, introspection, and UserInfo; supported PHP streams are the fallback transport.
2. Verify and extract the release
Keep these files together:
m7-identity-token-php-0.1.2.zip
m7-identity-token-php-0.1.2.zip.sha256
m7-identity-token-php-0.1.2.zip.manifest.json
Verify the archive with one available command:
shasum -a 256 -c m7-identity-token-php-0.1.2.zip.sha256
sha256sum -c m7-identity-token-php-0.1.2.zip.sha256
Extract it into an application-owned, non-public package directory:
unzip m7-identity-token-php-0.1.2.zip -d ./vendor
The archive creates m7-identity-token-php-0.1.2/ and includes its autoloader,
source, package metadata, documentation, manifest, and payload checksums.
3. Load the package
Load the bundled autoloader from the extracted release:
require_once __DIR__ . '/vendor/m7-identity-token-php-0.1.2/autoload.php';
Do not edit the extracted package in place. Keep the archive manifest and digest as the installation receipt, and install a new verified release when upgrading.
4. Validate a token locally
The following command reads the serialized token from standard input so it does not need to appear in the process argument list:
<?php
require_once __DIR__ . '/vendor/m7-identity-token-php-0.1.2/autoload.php';
use M7\Identity\M7IdentitySDK;
$serializedToken = trim(stream_get_contents(STDIN));
if ($serializedToken === '') {
fwrite(STDERR, "A token is required on standard input.\n");
exit(2);
}
$certificate = file_get_contents('/path/to/trusted-public-certificate.pem');
$identity = new M7IdentitySDK();
$report = $identity->validate($serializedToken, [
'audience' => 'https://api.example.m7.org/',
'client_id' => 'YOUR_REGISTERED_CLIENT_ID',
'principal_type' => 'consumer',
'scope' => ['profile.read'],
'cert_pem' => $certificate,
]);
if (!$report->ok()) {
fwrite(STDERR, $report->reason() . "\n");
exit(1);
}
fwrite(STDOUT, "Token validation passed.\n");
Read the token from the consuming process's protected runtime channel. Do not store it in the script or use a literal token in a shell command.
5. Add live operations only when required
clientCredentials() needs an HTTPS token endpoint, a confidential client, and
at least one audience. introspect() needs an HTTPS introspection endpoint and
the registered client authentication method. userinfo() needs the
protected-resource endpoint and, for built-in M7 selectors, the registered
client ID. Store any client secret in the process secret manager and inject it
only into the trusted runtime.
Use bounded connection and response settings. Treat active() === false,
transport failures, malformed responses, and subject mismatches as closed
authorization outcomes.