## Overview
-There are two general flows of authentication:
+There are two general flows of authentication, each with a few variations:
* __Ephemeral / Stateless__: The client submits a singlular request (such as an API call) which includes credentials. The request is authenticated and processed, but then it is abandoned.
There are a couple flavors of stateless authentication:
* __X-Header (`xheader`)__: The credential is again submitted with an HTTP header (`X-Civi-Auth:`). The header behaves the same as the common header. The
differing name means that clients must specifically support it, but it also reduces the odsd of interference.
* __Persistent / Stateful__: The client makes a request for a persistent session, attaching the contact ID and/or user ID. These will be used in subsequent requests.
- * __End-point session (`endpoint`)__: The client submits an explicit authentication request (`POST /civicrm/authx/login?_authx=<credential>`) which creates a session and cookie.
+ * __End-point session (`login`)__: The client submits an explicit authentication request (`POST /civicrm/authx/login?_authx=<credential>`) which creates a session and cookie.
The authenticated session endures until one logs out (`/civicrm/authx/logout`).
* __Auto session (`auto`)__: The clients submits a GET request for any page (`?_authx=<credential>&_authxSes=1`). The session is initialized. The user redirects
to original page.
* Accepted credentials (`authx_xheader_cred`): `['jwt']`
* User link (`authx_xheader_user`): `'optional'`
* Persistent: End-point session flow
- * Accepted credentials (`authx_endpoint_cred`): `['jwt']`
- * User link (`authx_endpoint_user`): `require`
+ * Accepted credentials (`authx_login_cred`): `['jwt']`
+ * User link (`authx_login_user`): `require`
* Persistent: Auto session flow
* Accepted credentials (`authx_auto_cred`): `['paramalogin']` for Joomla, and `[]` for all others
* User link (`authx_auto_user`): `require`
### JSON Web Token
+By default, JSON Web Tokens are accepted for authentication in all flows.
+
+To use JWT authentication, you must first prepare a token on the server:
+
```php
-// First, on the server, prepare a token
-$token = Civi::service('authx.jwt')->create([
- 'contact_id' => 123,
- 'ttl' => 5*60*60,
+$token = Civi::service('crypto.jwt')->encode([
+ 'exp' => time() + 5*60, // Expires in 5 minutes
+ 'sub' => 'cid:203', // Subject (contact ID)
+ 'scope' => 'authx', // Allow general authentication
]);
+```
+
+This `$token` should be given to some other agent (e.g. web browser, custom script, or email client).
+
+For example, here's a custom script which uses the `$token` to call APIv3 (`Contact.get`). The token is based with the common HTTP authorization header:
-// Next, on the client, use this same token
+```php
$options = ['http' => [
- 'method' => 'GET',
- 'header' => 'Authorization: Bearer '.$token
+ 'method' => 'GET',
+ 'header' => "Authorization: Bearer $token",
]];
+$url = 'https://example.org/civicrm/ajax/rest?entity=Contact&action=get&json='
+ . urlencode(json_encode(["id" => "user_contact_id"]));
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
```
-### Username and Password
+Alternatively, if you needed to send an email with a sign-in link, the JWT could be passed as an `?_authx` parameter.
```php
-$auth = base64_encode("username:password");
-$context = stream_context_create([
- "http" => [
- "header" => "Authorization: Basic $auth"
- ]
-]);
-$homepage = file_get_contents("http://example.com/file", false, $context );
+$url = CRM_Utils_System::url('civicrm/dashboard', [
+ '_authx' => "Bearer $token",
+ '_authxSes' => 1,
+], TRUE, NULL, FALSE);
+$html = sprintf('<body>Here is your login link: <a href="%s">%s</a></body>',
+ htmlentities($url), htmlentities($url));
+CRM_Utils_Mail::send([...'html' => $html...]);
+```
+
+### Username and Password
+
+By default, username/password authentication is not enabled.
+
+```
+$ curl 'https://demouser:demopass@example.org/civicrm/authx/id'
+HTTP 401 Password authentication is not supported
+```
+
+However, if you activate it, then it will work with standard HTTP clients:
+
```
+$ cv ev 'Civi::settings()->set("authx_header_cred", ["pass","jwt"]);'
+
+$ curl 'https://demouser:demopass@example.org/civicrm/authx/id'
+{"contact_id":203,"user_id":"2"}
+```
+
+The "AuthX: Authenticate to services with password" CiviCRM permission must
+also be granted for the role associated to the user.