Merge pull request #23283 from eileenmcnaughton/import_saved_map
[civicrm-core.git] / ext / authx / README.md
CommitLineData
9e99ef4a
TO
1# AuthX
2
3The AuthX extension provides support for additional authentication protocols on CiviCRM pages.
4This is useful for automated testing and developing multi-modal pageflows (eg email => HTTP).
5
6## Overview
7
b9cbf1a6 8There are two general flows of authentication, each with a few variations:
9e99ef4a
TO
9
10* __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.
11 There are a couple flavors of stateless authentication:
12 * __Parameter (`param`)__: The credential is submitted with an HTTP GET or POST parameter (`?_authx=<credential>`)
13 * __Common Header (`header`)__: The credential is submitted with an HTTP (`Authorization:`). Depending on the credential, this will use either `Basic` or `Bearer`.
14 The standard header is easier to integrate with external applications; however, other features or plugins in the CMS may interfere with correct operation.
15 * __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
16 differing name means that clients must specifically support it, but it also reduces the odsd of interference.
17* __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.
d0528c96 18 * __End-point session (`login`)__: The client submits an explicit authentication request (`POST /civicrm/authx/login?_authx=<credential>`) which creates a session and cookie.
9e99ef4a
TO
19 The authenticated session endures until one logs out (`/civicrm/authx/logout`).
20 * __Auto session (`auto`)__: The clients submits a GET request for any page (`?_authx=<credential>&_authxSes=1`). The session is initialized. The user redirects
21 to original page.
22
23Each flow may (configurably) accept any of these credentials:
24
25* __JSON Web Tokens (`jwt`)__: These tokens must be generated by Civi using a cryptographic signing key and expiration time.
26 The client submits the token as its sole credential.
27* __API Key (`api_key`)__: The user configures a value for `civicrm_contact.api_key`. The client submits
28 the token as its sole credential.
29* __Username/Password (`pass`)__: The client submits the username and password for a CMS user.
30
31CiviCRM `Contact` records are often linked to CMS `User` records -- but not always. There are different ways to approach this matching:
32
33* __Ignore__: Ignore any related `User` accounts. From a CMS perspective, the user is anonymous.
34* __Optional__: If there is a correlated CMS `User`, then load it. If there isn't, leave the CMS user as anonymous.
35* __Require__: Only allow authentication if proceed if there is a correlated user account.
36
37## Configuration
38
39For each authentication flow, one may toggle support for different credentials and user-links. Here is the default configuration:
40
41* Ephemeral: Parameter flow
42 * Accepted credentials (`authx_param_cred`): `['jwt']`
43 * User link (`authx_param_user`): `'optional'`
44* Ephemeral: Common header flow
45 * Accepted credentials (`authx_header_cred`): `['jwt']`
46 * User link (`authx_header_user`): `'optional'`
47* Ephemeral: X header flow
48 * Accepted credentials (`authx_xheader_cred`): `['jwt']`
49 * User link (`authx_xheader_user`): `'optional'`
50* Persistent: End-point session flow
d0528c96
TO
51 * Accepted credentials (`authx_login_cred`): `['jwt']`
52 * User link (`authx_login_user`): `require`
9e99ef4a
TO
53* Persistent: Auto session flow
54 * Accepted credentials (`authx_auto_cred`): `['paramalogin']` for Joomla, and `[]` for all others
55 * User link (`authx_auto_user`): `require`
56
57## Quirks and Compatibility
58
59Some modes may not be supported in some environments. For example:
60
61* __Joomla, WordPress__: Creates extraneous sessions (e.g. even if the request is for stateless authentication).
62* __WordPress__: The default `.htaccess` in WordPress may obscure the common `Authorization:` header. Fix this by adding:
63 ```
64 SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
65 ```
66
67## Examples
68
69### JSON Web Token
70
b9cbf1a6
TO
71By default, JSON Web Tokens are accepted for authentication in all flows.
72
73To use JWT authentication, you must first prepare a token on the server:
74
9e99ef4a 75```php
b9cbf1a6
TO
76$token = Civi::service('crypto.jwt')->encode([
77 'exp' => time() + 5*60, // Expires in 5 minutes
78 'sub' => 'cid:203', // Subject (contact ID)
79 'scope' => 'authx', // Allow general authentication
9e99ef4a 80]);
b9cbf1a6
TO
81```
82
83This `$token` should be given to some other agent (e.g. web browser, custom script, or email client).
84
85For 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:
9e99ef4a 86
b9cbf1a6 87```php
9e99ef4a 88$options = ['http' => [
b9cbf1a6
TO
89 'method' => 'GET',
90 'header' => "Authorization: Bearer $token",
9e99ef4a 91]];
b9cbf1a6
TO
92$url = 'https://example.org/civicrm/ajax/rest?entity=Contact&action=get&json='
93 . urlencode(json_encode(["id" => "user_contact_id"]));
9e99ef4a
TO
94$context = stream_context_create($options);
95$response = file_get_contents($url, false, $context);
7946d659
TO
96```
97
b9cbf1a6 98Alternatively, if you needed to send an email with a sign-in link, the JWT could be passed as an `?_authx` parameter.
7946d659 99
9e99ef4a 100```php
b9cbf1a6
TO
101$url = CRM_Utils_System::url('civicrm/dashboard', [
102 '_authx' => "Bearer $token",
103 '_authxSes' => 1,
104], TRUE, NULL, FALSE);
105$html = sprintf('<body>Here is your login link: <a href="%s">%s</a></body>',
106 htmlentities($url), htmlentities($url));
107CRM_Utils_Mail::send([...'html' => $html...]);
108```
109
110### Username and Password
111
112By default, username/password authentication is not enabled.
113
114```
115$ curl 'https://demouser:demopass@example.org/civicrm/authx/id'
116HTTP 401 Password authentication is not supported
117```
118
119However, if you activate it, then it will work with standard HTTP clients:
120
121```
122$ cv ev 'Civi::settings()->set("authx_header_cred", ["pass","jwt"]);'
123
124$ curl 'https://demouser:demopass@example.org/civicrm/authx/id'
125{"contact_id":203,"user_id":"2"}
7946d659 126```
54ff24d7
ML
127
128The "AuthX: Authenticate to services with password" CiviCRM permission must
129also be granted for the role associated to the user.