SAML Authentication
SupportPal supports Secure Assertion Markup Language (SAML), which allows you to provide single sign-on (SSO) authentication for both users and operators. Different identity providers can be configured for both users and operators to allow greater flexibility.
Dependencies
In order to use SAML Authentication your server must have the following PHP extensions installed (beyond SupportPal required requirements):
- php-date
- php-zlib
- php-gettext
Enabling SAML
SAML Authentication can be enabled by creating a config/production/saml.php
file. An example file, with the basic configuration items can be seen below:
<?php
use App\Modules\User\Controllers\Saml\SamlAuthManager;
return [
/*
|----------------------------------------------------------------
| Strict Mode
|----------------------------------------------------------------
|
| If 'strict' is True, then the PHP Toolkit will reject unsigned
| or unencrypted messages if it expects them signed or encrypted
| Also will reject the messages if not strictly follow the SAML
| standard: Destination, NameId, Conditions ... are validated too.
|
*/
'strict' => true,
/*
|--------------------------------------------------------------------------
| SAML Manager
|--------------------------------------------------------------------------
|
| Define different SAML authentication settings for the frontend and
| operator panels. Defining an IdP will enable SAML for the respective
| panel.
|
*/
'guards' => [
SamlAuthManager::FRONTEND_GUARD => [
// Whether to allow users to login via both SupportPal and IdP, or
// only via the IdP.
'dualLogin' => false,
// Identity Provider Data that we want connect with our SP
'idp' => [
// The name of the identity provider, shown on the interface as
// 'log in via :name'.
'name' => 'IdP',
// Identifier of the IdP entity (must be a URI)
'entityId' => '...',
// SSO endpoint info of the IdP. (Authentication Request protocol)
'singleSignOnService' => [
'url' => '...',
],
// SLO endpoint info of the IdP.
'singleLogoutService' => [
'url' => '...',
],
// Public x509 certificate of the IdP
'x509cert' => '...',
],
],
SamlAuthManager::OPERATOR_GUARD => [
],
],
];
Guards allow you to define different SAML Authentication settings per brand, and also operator login. If a guard does not define any configuration items, or provides an invalid configuration, SAML Authentication will not be enabled. For example, in the previous example SAML Authentication is only enabled on the frontend portal.
If both guards use the same IdP configuration, please copy and paste so that SamlAuthManager::FRONTEND_GUARD => [ ... ]
and SamlAuthManager::OPERATOR_GUARD => [ ... ]
contain the same content.
Brand Guards
The SamlAuthManager::FRONTEND_GUARD => [ ... ]
is the default guard which will be used for any brands that don't define a configuration.
If you have multiple brands and only want to enable SAML for some of them please do not use this format.
To define per brand guards, SamlAuthManager::FRONTEND_GUARD . '1' => [ ... ]
should be used where 1
represents the ID of the brand.
The brand ID can be found by browsing to Settings > Brands > Edit Brand in the operator panel and extracting the ID from the URL:
/admin/settings/core/brand/1/edit
Dual Login
By default dual login is enabled and allows users to choose whether to login via SupportPal or the IdP. This can optionally be turned off by setting 'dualLogin' => 'false'
for the appropriate SAML guard. When dual login is disabled, the user will be automatically redirected directly to the IdP - completely bypassing the SupportPal login screen. If enabled for operators and you lose access for whatever reason, please set dualLogin back to true
, or delete the configuration item from the file.
Service Provider
The service provider is controlled by SupportPal and uses the following routes:
Guard | Entity ID | Assertion Consumer Service (ACS) | Single Logout Service (SLS) |
---|---|---|---|
Frontend | /frontend/saml/metadata | /frontend/saml/acs | /frontend/saml/sls |
Operator | /operator/saml/metadata | /operator/saml/acs | /operator/saml/sls |
Each of these routes should be appended to your SupportPal base URL. For example: https://www.supportpal.com/support/operator/saml/metadata
In the vast majority of situations you will not need to modify the service providers configuration. That being said, if you need the service provider metadata to be signed you will need to specify certificate information:
x509cert
- Whole public x509 certificate as a stringprivateKey
- Private key for the certificate
An example configuration file can be found below, some information has been omitted (shown as ...).
<?php
return [
...
'guards' => [
SamlAuthManager::FRONTEND_GUARD => [
'sp' => [
'x509cert' => '<PRIVATECERT>',
'privateKey' => '<PRIVATEKEY>',
/*
* Key rollover
* If you plan to update the SP x509cert and privateKey
* you can define here the new x509cert and it will be
* published on the SP metadata so Identity Providers can
* read them and get ready for rollover.
*/
// 'x509certNew' => '',
],
// Identity Provider Data that we want connect with our SP
'idp' => [
...
],
],
],
];
Identity Service Provider (IdP)
To enable SAML authentication, you usually need 4 pieces of information (see in the previous example):
entityId
- Base URI of the IdP-
singleSignOnService
url
- Absolute URI for the single sign on service
-
singleLogoutService
url
- Absolute URI for the single logout service
x509cert
- Whole public x509 certificate of the IdP as a string
It's also possible to optionally specify custom attribute names for SAML user account information. For example, urn:oid:2.16.840.1.113730.3.1.241
isfullname
and urn:oid:0.9.2342.19200300.100.1.3
is email
. For more information see 'attributes'
section below.
Additional Configuration Items
SupportPal also allows you complete control over the SAML service configuration (beyond the basic necessary items described above). Please find the full configuration, with descriptions, below:
<?php
use App\Modules\User\Controllers\Saml\SamlAuthManager;
return [
/*
|----------------------------------------------------------------
| Strict Mode
|----------------------------------------------------------------
|
| If 'strict' is True, then the PHP Toolkit will reject unsigned
| or unencrypted messages if it expects them signed or encrypted
| Also will reject the messages if not strictly follow the SAML
| standard: Destination, NameId, Conditions ... are validated too.
|
*/
'strict' => true,
/*
|--------------------------------------------------------------------------
| SAML Manager
|--------------------------------------------------------------------------
|
| Define different SAML authentication settings for the frontend and
| operator panels. Defining an IdP will enable SAML for the respective
| panel.
|
*/
'guards' => [
SamlAuthManager::FRONTEND_GUARD => [
// Indicates how the parameters will be retrieved from the sls request for signature validation
'retrieveParametersFromServer' => false,
// Whether to allow users to login via both SupportPal and IdP, or
// only via the IdP.
'dualLogin' => false,
// Identity Provider Data that we want connect with our SP
'idp' => [
// The name of the identity provider, shown on the interface as
// 'log in via :name'.
'name' => 'IdP',
// Identifier of the IdP entity (must be a URI)
'entityId' => '',
// SSO endpoint info of the IdP. (Authentication Request protocol)
'singleSignOnService' => [
// URL Target of the IdP where the SP will send the Authentication Request Message
'url' => '',
// SAML protocol binding to be used when returning the <Response>
// message. Onelogin Toolkit supports for this endpoint the
// HTTP-POST binding only
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
],
// SLO endpoint info of the IdP.
'singleLogoutService' => [
// URL Location of the IdP where the SP will send the SLO Request
'url' => '',
// URL location of the IdP where the SP will send the SLO Response (ResponseLocation)
// if not set, url for the SLO Request will be used
'responseUrl' => '',
// SAML protocol binding to be used when returning the <Response>
// message. Onelogin Toolkit supports for this endpoint the
// HTTP-Redirect binding only
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
],
// Public x509 certificate of the IdP
'x509cert' => '',
/*
* Instead of use the whole x509cert you can use a fingerprint in
* order to validate the SAMLResponse, but we don't recommend to use
* that method on production since is exploitable by a collision
* attack.
* (openssl x509 -noout -fingerprint -in "idp.crt" to generate it,
* or add for example the -sha256 , -sha384 or -sha512 parameter)
*
* If a fingerprint is provided, then the certFingerprintAlgorithm is required in order to
* let the toolkit know which algorithm was used. Possible values: sha1, sha256, sha384 or sha512
* 'sha1' is the default value.
*
* Notice that if you want to validate any SAML Message sent by the HTTP-Redirect binding, you
* will need to provide the whole x509cert.
*/
// 'certFingerprint' => '',
// 'certFingerprintAlgorithm' => 'sha1',
/* In some scenarios the IdP uses different certificates for
* signing/encryption, or is under key rollover phase and more
* than one certificate is published on IdP metadata.
* In order to handle that the toolkit offers that parameter.
* (when used, 'x509cert' and 'certFingerprint' values are
* ignored).
*/
// 'x509certMulti' => array(
// 'signing' => array(
// 0 => '<cert1-string>',
// ),
// 'encryption' => array(
// 0 => '<cert2-string>',
// )
// ),
// Custom attribute names. Change the value if your IdP uses different
// attribute names e.g. 'fullname' => 'urn:oid:2.16.840.1.113730.3.1.241'
'attributes' => [
'brand_id' => 'brand_id',
'firstname' => 'firstname',
'lastname' => 'lastname',
'fullname' => 'fullname',
'email' => 'email',
'role' => 'role',
'language' => 'language',
'timezone' => 'timezone',
'country' => 'country',
'groups' => 'groups',
'departments' => 'departments',
'organisation_id' => 'organisation_id',
'organisation_access_level' => 'organisation_access_level'
],
],
// Security settings
'security' => [
// Indicates that the nameID of the <samlp:logoutRequest> sent by this SP
// will be encrypted.
'nameIdEncrypted' => false,
// Indicates whether the <samlp:AuthnRequest> messages sent by this SP
// will be signed. [Metadata of the SP will offer this info]
'authnRequestsSigned' => false,
// Indicates whether the <samlp:logoutRequest> messages sent by this SP
// will be signed.
'logoutRequestSigned' => false,
// Indicates whether the <samlp:logoutResponse> messages sent by this SP
// will be signed.
'logoutResponseSigned' => false,
/* Sign the Metadata
False || True (use sp certs) || array (
keyFileName => 'metadata.key',
certFileName => 'metadata.crt'
)
*/
'signMetadata' => false,
// Indicates a requirement for the <samlp:Response>, <samlp:LogoutRequest>
// and <samlp:LogoutResponse> elements received by this SP to be signed.
'wantMessagesSigned' => false,
// Indicates a requirement for the <saml:Assertion> elements received by
// this SP to be encrypted.
'wantAssertionsEncrypted' => false,
// Indicates a requirement for the <saml:Assertion> elements received by
// this SP to be signed. [Metadata of the SP will offer this info]
'wantAssertionsSigned' => false,
// Indicates a requirement for the NameID element on the SAMLResponse
// received by this SP to be present.
'wantNameId' => true,
// Indicates a requirement for the NameID received by
// this SP to be encrypted.
'wantNameIdEncrypted' => false,
// Authentication context.
// Set to false or don't present this parameter and no AuthContext will be sent in the AuthNRequest,
// Set true and you will get an AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'
// Set an array with the possible auth context values: array ('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509'),
'requestedAuthnContext' => true,
// Indicates if the SP will validate all received xmls.
// (In order to validate the xml, 'strict' and 'wantXMLValidation' must be true).
'wantXMLValidation' => true,
// If true, SAMLResponses with an empty value at its Destination
// attribute will not be rejected for this fact.
'relaxDestinationValidation' => false,
// Algorithm that the toolkit will use on signing process. Options:
// 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
// 'http://www.w3.org/2000/09/xmldsig#dsa-sha1'
// 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
// 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384'
// 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512'
'signatureAlgorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
// Algorithm that the toolkit will use on digest process. Options:
// 'http://www.w3.org/2000/09/xmldsig#sha1'
// 'http://www.w3.org/2001/04/xmlenc#sha256'
// 'http://www.w3.org/2001/04/xmldsig-more#sha384'
// 'http://www.w3.org/2001/04/xmlenc#sha512'
// Notice that sha1 is a deprecated algorithm and should not be used
'digestAlgorithm' => 'http://www.w3.org/2001/04/xmlenc#sha256',
// ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses
// uppercase. Turn it True for ADFS compatibility on signature verification
'lowercaseUrlencoding' => false,
],
],
SamlAuthManager::OPERATOR_GUARD => [
],
],
];
Automatically Creating Accounts within SupportPal
The following attributes can be set in SAML and are used for the automatic creation of new users or operators within SupportPal. If the user already exists in the system, any SAML attributes will be ignored:
Attribute Name | Description | Required |
---|---|---|
role |
Whether the person authenticating is a user or an operator. Valid values: 'user' or 'operator' . |
Required if auto-generating an operator. |
fullname |
The user's full name will automatically be split into first and last names. Alternatively, specify firstname and lastname attributes individually. |
Yes |
email |
Email address for the user. | Yes |
brand_id |
Which brand to associate the user with. Defaults to "Default Brand" as defined in General Settings. | No |
language_code |
language code - the language must exist within SupportPal. | No |
timezone |
Timezone the user lives in. A full list of valid values can be found below. | No |
country |
2 letter country code for the country that the user lives in. A full list of valid values can be found below. | No |
organisation_id |
User only attribute. Associate the user with an existing organisation in SupportPal. | No |
organisation_access_level |
User only attribute. A value of 0 represents MANAGER, a value of 1 represents USER. Defaults to 1 (User). See Organisation Access Levels for more information. | No |
phone_numbers |
Comma delimited list of phone numbers. Must be in E.164 international format. | No |
groups |
Comma delimited list of group IDs. If no user group is provided when creating an operator, all operator groups in the system are used. | No |
departments |
Operator only attribute. Comma delimited list of department IDs. Only relevant when auto-generating an operator account. | No |
Valid Timezones
Africa/Algiers
Africa/Cairo
Africa/Casablanca
Africa/Harare
Africa/Monrovia
Africa/Nairobi
Africa/Windhoek
America/Anchorage
America/Los_Angeles
America/Tijuana
America/Denver
America/Chihuahua
America/Mazatlan
America/Phoenix
America/Regina
America/Tegucigalpa
America/Chicago
America/Mexico_City
America/Monterrey
America/New_York
America/Bogota
America/Lima
America/Rio_Branco
America/Indiana/Indianapolis
America/Caracas
America/Halifax
America/Manaus
America/Santiago
America/La_Paz
America/St_Johns
America/Argentina/Buenos_Aires
America/Sao_Paulo
America/Godthab
America/Montevideo
Asia/Jerusalem
Asia/Amman
Asia/Beirut
Asia/Kuwait
Asia/Riyadh
Asia/Baghdad
Asia/Tbilisi
Asia/Tehran
Asia/Muscat
Asia/Baku
Asia/Yerevan
Asia/Yekaterinburg
Asia/Karachi
Asia/Tashkent
Asia/Kolkata
Asia/Colombo
Asia/Katmandu
Asia/Dhaka
Asia/Almaty
Asia/Novosibirsk
Asia/Rangoon
Asia/Krasnoyarsk
Asia/Bangkok
Asia/Jakarta
Asia/Brunei
Asia/Chongqing
Asia/Hong_Kong
Asia/Urumqi
Asia/Irkutsk
Asia/Ulaanbaatar
Asia/Kuala_Lumpur
Asia/Singapore
Asia/Taipei
Asia/Seoul
Asia/Tokyo
Asia/Yakutsk
Asia/Vladivostok
Asia/Magadan
Asia/Kamchatka
Atlantic/South_Georgia
Atlantic/Azores
Atlantic/Cape_Verde
Atlantic/Reykjavik
Australia/Perth
Australia/Darwin
Australia/Adelaide
Australia/Canberra
Australia/Melbourne
Australia/Sydney
Australia/Brisbane
Australia/Hobart
Europe/Dublin
Europe/Lisbon
Europe/London
Europe/Belgrade
Europe/Bratislava
Europe/Budapest
Europe/Ljubljana
Europe/Prague
Europe/Sarajevo
Europe/Skopje
Europe/Warsaw
Europe/Zagreb
Europe/Brussels
Europe/Copenhagen
Europe/Madrid
Europe/Paris
Europe/Amsterdam
Europe/Berlin
Europe/Rome
Europe/Stockholm
Europe/Vienna
Europe/Minsk
Europe/Helsinki
Europe/Riga
Europe/Sofia
Europe/Tallinn
Europe/Vilnius
Europe/Athens
Europe/Bucharest
Europe/Istanbul
Europe/Moscow
Europe/Volgograd
Pacific/Midway
Pacific/Samoa
Pacific/Honolulu
Pacific/Guam
Pacific/Port_Moresby
Pacific/Fiji
Pacific/Auckland
Pacific/Tongatapu
Valid Countries
AF => Afghanistan,
AL => Albania,
DZ => Algeria,
AS => American Samoa,
AD => Andorra,
AO => Angola,
AI => Anguilla,
AQ => Antarctica,
AG => Antigua and Barbuda,
AR => Argentina,
AM => Armenia,
AW => Aruba,
AU => Australia,
AT => Austria,
AZ => Azerbaijan,
BS => Bahamas,
BH => Bahrain,
BD => Bangladesh,
BB => Barbados,
BY => Belarus,
BE => Belgium,
BZ => Belize,
BJ => Benin,
BM => Bermuda,
BT => Bhutan,
BO => Bolivia,
BA => Bosnia and Herzegovina,
BW => Botswana,
BV => Bouvet Island,
BR => Brazil,
BQ => British Antarctic Territory,
IO => British Indian Ocean Territory,
VG => British Virgin Islands,
BN => Brunei,
BG => Bulgaria,
BF => Burkina Faso,
BI => Burundi,
KH => Cambodia,
CM => Cameroon,
CA => Canada,
CT => Canton and Enderbury Islands,
CV => Cape Verde,
KY => Cayman Islands,
CF => Central African Republic,
TD => Chad,
CL => Chile,
CN => China,
CX => Christmas Island,
CC => Cocos [Keeling] Islands,
CO => Colombia,
KM => Comoros,
CG => Congo - Brazzaville,
CD => Congo - Kinshasa,
CK => Cook Islands,
CR => Costa Rica,
HR => Croatia,
CU => Cuba,
CY => Cyprus,
CZ => Czech Republic,
CI => Côte d’Ivoire,
DK => Denmark,
DJ => Djibouti,
DM => Dominica,
DO => Dominican Republic,
NQ => Dronning Maud Land,
DD => East Germany,
EC => Ecuador,
EG => Egypt,
SV => El Salvador,
GQ => Equatorial Guinea,
ER => Eritrea,
EE => Estonia,
ET => Ethiopia,
FK => Falkland Islands,
FO => Faroe Islands,
FJ => Fiji,
FI => Finland,
FR => France,
GF => French Guiana,
PF => French Polynesia,
TF => French Southern Territories,
FQ => French Southern and Antarctic Territories,
GA => Gabon,
GM => Gambia,
GE => Georgia,
DE => Germany,
GH => Ghana,
GI => Gibraltar,
GR => Greece,
GL => Greenland,
GD => Grenada,
GP => Guadeloupe,
GU => Guam,
GT => Guatemala,
GG => Guernsey,
GN => Guinea,
GW => Guinea-Bissau,
GY => Guyana,
HT => Haiti,
HM => Heard Island and McDonald Islands,
HN => Honduras,
HK => Hong Kong SAR China,
HU => Hungary,
IS => Iceland,
IN => India,
ID => Indonesia,
IR => Iran,
IQ => Iraq,
IE => Ireland,
IM => Isle of Man,
IL => Israel,
IT => Italy,
JM => Jamaica,
JP => Japan,
JE => Jersey,
JT => Johnston Island,
JO => Jordan,
KZ => Kazakhstan,
KE => Kenya,
KI => Kiribati,
KW => Kuwait,
KG => Kyrgyzstan,
LA => Laos,
LV => Latvia,
LB => Lebanon,
LS => Lesotho,
LR => Liberia,
LY => Libya,
LI => Liechtenstein,
LT => Lithuania,
LU => Luxembourg,
MO => Macau SAR China,
MK => Macedonia,
MG => Madagascar,
MW => Malawi,
MY => Malaysia,
MV => Maldives,
ML => Mali,
MT => Malta,
MH => Marshall Islands,
MQ => Martinique,
MR => Mauritania,
MU => Mauritius,
YT => Mayotte,
FX => Metropolitan France,
MX => Mexico,
FM => Micronesia,
MI => Midway Islands,
MD => Moldova,
MC => Monaco,
MN => Mongolia,
ME => Montenegro,
MS => Montserrat,
MA => Morocco,
MZ => Mozambique,
MM => Myanmar [Burma],
NA => Namibia,
NR => Nauru,
NP => Nepal,
NL => Netherlands,
AN => Netherlands Antilles,
NT => Neutral Zone,
NC => New Caledonia,
NZ => New Zealand,
NI => Nicaragua,
NE => Niger,
NG => Nigeria,
NU => Niue,
NF => Norfolk Island,
KP => North Korea,
VD => North Vietnam,
MP => Northern Mariana Islands,
NO => Norway,
OM => Oman,
PC => Pacific Islands Trust Territory,
PK => Pakistan,
PW => Palau,
PS => Palestinian Territories,
PA => Panama,
PZ => Panama Canal Zone,
PG => Papua New Guinea,
PY => Paraguay,
YD => People\s Democratic Republic of Yemen,
PE => Peru,
PH => Philippines,
PN => Pitcairn Islands,
PL => Poland,
PT => Portugal,
PR => Puerto Rico,
QA => Qatar,
RO => Romania,
RU => Russia,
RW => Rwanda,
RE => Réunion,
BL => Saint Barthélemy,
SH => Saint Helena,
KN => Saint Kitts and Nevis,
LC => Saint Lucia,
MF => Saint Martin,
PM => Saint Pierre and Miquelon,
VC => Saint Vincent and the Grenadines,
WS => Samoa,
SM => San Marino,
SA => Saudi Arabia,
SN => Senegal,
RS => Serbia,
CS => Serbia and Montenegro,
SC => Seychelles,
SL => Sierra Leone,
SG => Singapore,
SK => Slovakia,
SI => Slovenia,
SB => Solomon Islands,
SO => Somalia,
ZA => South Africa,
GS => South Georgia and the South Sandwich Islands,
KR => South Korea,
ES => Spain,
LK => Sri Lanka,
SD => Sudan,
SR => Suriname,
SJ => Svalbard and Jan Mayen,
SZ => Swaziland,
SE => Sweden,
CH => Switzerland,
SY => Syria,
ST => São Tomé and Príncipe,
TW => Taiwan,
TJ => Tajikistan,
TZ => Tanzania,
TH => Thailand,
TL => Timor-Leste,
TG => Togo,
TK => Tokelau,
TO => Tonga,
TT => Trinidad and Tobago,
TN => Tunisia,
TR => Turkey,
TM => Turkmenistan,
TC => Turks and Caicos Islands,
TV => Tuvalu,
UM => U.S. Minor Outlying Islands,
PU => U.S. Miscellaneous Pacific Islands,
VI => U.S. Virgin Islands,
UG => Uganda,
UA => Ukraine,
SU => Union of Soviet Socialist Republics,
AE => United Arab Emirates,
GB => United Kingdom,
US => United States,
UY => Uruguay,
UZ => Uzbekistan,
VU => Vanuatu,
VA => Vatican City,
VE => Venezuela,
VN => Vietnam,
WK => Wake Island,
WF => Wallis and Futuna,
EH => Western Sahara,
YE => Yemen,
ZM => Zambia,
ZW => Zimbabwe,
AX => Åland Islands,
Third-Party Configurations
Some of our users have kindly provided guides on how to configure SAML with various external services:
If you configure SAML for a different service and would like to share a guide, please get in touch via support ticket - we would love to hear from you.
Debugging
If SAML is configured incorrectly you will most likely receive unexpected results when logging in / out of SupportPal. To understand what the problem is please follow the below steps:
- Enable Debug Mode via Settings > General Settings > Debug (tab). Alternatively, if you can't login to the operator panel enable it by setting
'debug' => true,
in config/production/app.php - for manually updating configuration files please read Updating Config Files. - Retry whatever you were doing that caused the error to occur
- Read the application log file for today:
/storage/logs/supportpal-x-x-x.log
- Once the problem has been resolved, please disable debug mode (otherwise it will affect the performance of the application).
Please contact us via support ticket and attach the log file if you're unsure what the error means.