simplesamlphp-1.15.3/ 0000755 0000000 0000000 00000000000 13245225041 013153 5 ustar root root simplesamlphp-1.15.3/metadata-templates/ 0000755 0000000 0000000 00000000000 13245225037 016734 5 ustar root root simplesamlphp-1.15.3/metadata-templates/adfs-idp-hosted.php 0000644 0000000 0000000 00000000450 13245225037 022417 0 ustar root root '__DEFAULT__',
'privatekey' => 'server.pem',
'certificate' => 'server.crt',
'auth' => 'example-userpass',
'authproc' => array(
// Convert LDAP names to WS-Fed Claims.
100 => array('class' => 'core:AttributeMap', 'name2claim'),
),
);
simplesamlphp-1.15.3/metadata-templates/saml20-idp-hosted.php 0000644 0000000 0000000 00000004506 13245225037 022606 0 ustar root root '__DEFAULT__',
// X.509 key and certificate. Relative to the cert directory.
'privatekey' => 'server.pem',
'certificate' => 'server.crt',
/*
* Authentication source to use. Must be one that is configured in
* 'config/authsources.php'.
*/
'auth' => 'example-userpass',
/*
* WARNING: SHA-1 is disallowed starting January the 1st, 2014.
*
* Uncomment the following option to start using SHA-256 for your signatures.
* Currently, SimpleSAMLphp defaults to SHA-1, which has been deprecated since
* 2011, and will be disallowed by NIST as of 2014. Please refer to the following
* document for more information:
*
* http://csrc.nist.gov/publications/nistpubs/800-131A/sp800-131A.pdf
*
* If you are uncertain about service providers supporting SHA-256 or other
* algorithms of the SHA-2 family, you can configure it individually in the
* SP-remote metadata set for those that support it. Once you are certain that
* all your configured SPs support SHA-2, you can safely remove the configuration
* options in the SP-remote metadata set and uncomment the following option.
*
* Please refer to the IdP hosted reference for more information.
*/
//'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
/* Uncomment the following to use the uri NameFormat on attributes. */
/*
'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
'authproc' => array(
// Convert LDAP names to oids.
100 => array('class' => 'core:AttributeMap', 'name2oid'),
),
*/
/*
* Uncomment the following to specify the registration information in the
* exported metadata. Refer to:
* http://docs.oasis-open.org/security/saml/Post2.0/saml-metadata-rpi/v1.0/cs01/saml-metadata-rpi-v1.0-cs01.html
* for more information.
*/
/*
'RegistrationInfo' => array(
'authority' => 'urn:mace:example.org',
'instant' => '2008-01-17T11:28:03Z',
'policies' => array(
'en' => 'http://example.org/policy',
'es' => 'http://example.org/politica',
),
),
*/
);
simplesamlphp-1.15.3/metadata-templates/shib13-idp-hosted.php 0000644 0000000 0000000 00000001154 13245225037 022575 0 ustar root root '__DEFAULT__',
// X.509 key and certificate. Relative to the cert directory.
'privatekey' => 'server.pem',
'certificate' => 'server.crt',
/*
* Authentication source to use. Must be one that is configured in
* 'config/authsources.php'.
*/
'auth' => 'example-userpass',
);
simplesamlphp-1.15.3/metadata-templates/wsfed-idp-remote.php 0000644 0000000 0000000 00000000341 13245225037 022616 0 ustar root root 'https://localhost:9031/idp/prp.wsf',
'certificate' => 'pingfed-localhost.pem',
);
simplesamlphp-1.15.3/metadata-templates/shib13-sp-remote.php 0000644 0000000 0000000 00000000642 13245225037 022451 0 ustar root root 'http://sp.shiblab.feide.no/Shibboleth.sso/SAML/POST',
'audience' => 'urn:mace:feide:shiblab',
'base64attributes' => FALSE,
);
simplesamlphp-1.15.3/metadata-templates/adfs-sp-remote.php 0000644 0000000 0000000 00000000414 13245225037 022272 0 ustar root root 'https://localhost/adfs/ls/',
'simplesaml.nameidattribute' => 'uid',
'authproc' => array(
50 => array(
'class' => 'core:AttributeLimit',
'cn', 'mail', 'uid', 'eduPersonAffiliation',
),
),
);
simplesamlphp-1.15.3/metadata-templates/shib13-idp-remote.php 0000644 0000000 0000000 00000000601 13245225037 022576 0 ustar root root 'https://idp.example.org/shibboleth-idp/SSO',
'certificate' => 'example.pem',
);
*/
simplesamlphp-1.15.3/metadata-templates/saml20-sp-remote.php 0000644 0000000 0000000 00000002251 13245225037 022454 0 ustar root root 'https://saml2sp.example.org/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp',
'SingleLogoutService' => 'https://saml2sp.example.org/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp',
);
/*
* This example shows an example config that works with G Suite (Google Apps) for education.
* What is important is that you have an attribute in your IdP that maps to the local part of the email address
* at G Suite. In example, if your Google account is foo.com, and you have a user that has an email john@foo.com, then you
* must set the simplesaml.nameidattribute to be the name of an attribute that for this user has the value of 'john'.
*/
$metadata['google.com'] = array(
'AssertionConsumerService' => 'https://www.google.com/a/g.feide.no/acs',
'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
'simplesaml.nameidattribute' => 'uid',
'simplesaml.attributes' => FALSE,
);
simplesamlphp-1.15.3/metadata-templates/shib13-sp-hosted.php 0000644 0000000 0000000 00000000350 13245225037 022440 0 ustar root root '__DEFAULT__',
);
simplesamlphp-1.15.3/metadata-templates/saml20-idp-remote.php 0000644 0000000 0000000 00000000330 13245225037 022602 0 ustar root root '__DEFAULT__',
);
simplesamlphp-1.15.3/LICENSE 0000644 0000000 0000000 00000057647 13245225037 014210 0 ustar root root GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
simplesamlphp-1.15.3/tests/ 0000755 0000000 0000000 00000000000 13245225037 014322 5 ustar root root simplesamlphp-1.15.3/tests/modules/ 0000755 0000000 0000000 00000000000 13245225037 015772 5 ustar root root simplesamlphp-1.15.3/tests/modules/core/ 0000755 0000000 0000000 00000000000 13245225037 016722 5 ustar root root simplesamlphp-1.15.3/tests/modules/core/lib/ 0000755 0000000 0000000 00000000000 13245225037 017470 5 ustar root root simplesamlphp-1.15.3/tests/modules/core/lib/Auth/ 0000755 0000000 0000000 00000000000 13245225037 020371 5 ustar root root simplesamlphp-1.15.3/tests/modules/core/lib/Auth/Process/ 0000755 0000000 0000000 00000000000 13245225037 022007 5 ustar root root simplesamlphp-1.15.3/tests/modules/core/lib/Auth/Process/ScopeFromAttributeTest.php 0000644 0000000 0000000 00000007366 13245225037 027155 0 ustar root root process($request);
return $request;
}
/*
* Test the most basic functionality.
*/
public function testBasic()
{
$config = array(
'sourceAttribute' => 'eduPersonPrincipalName',
'targetAttribute' => 'scope',
);
$request = array(
'Attributes' => array(
'eduPersonPrincipalName' => array('jdoe@example.com'),
)
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('scope', $attributes);
$this->assertEquals($attributes['scope'], array('example.com'));
}
/*
* If scope already set, module must not overwrite.
*/
public function testNoOverwrite()
{
$config = array(
'sourceAttribute' => 'eduPersonPrincipalName',
'targetAttribute' => 'scope',
);
$request = array(
'Attributes' => array(
'eduPersonPrincipalName' => array('jdoe@example.com'),
'scope' => array('example.edu')
)
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['scope'], array('example.edu'));
}
/*
* If source attribute not set, nothing happens
*/
public function testNoSourceAttribute()
{
$config = array(
'sourceAttribute' => 'eduPersonPrincipalName',
'targetAttribute' => 'scope',
);
$request = array(
'Attributes' => array(
'mail' => array('j.doe@example.edu', 'john@example.org'),
'scope' => array('example.edu')
)
);
$result = self::processFilter($config, $request);
$this->assertEquals($request['Attributes'], $result['Attributes']);
}
/*
* When multiple @ signs in attribute, should use last one.
*/
public function testMultiAt()
{
$config = array(
'sourceAttribute' => 'eduPersonPrincipalName',
'targetAttribute' => 'scope',
);
$request = array(
'Attributes' => array(
'eduPersonPrincipalName' => array('john@doe@example.com'),
)
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['scope'], array('example.com'));
}
/*
* When the source attribute doesn't have a scope, a warning is emitted
* NOTE: currently disabled: this triggers a warning and a warning
* wants to start a session which we cannot do in phpunit. How to fix?
*/
public function testNoAt()
{
$config = array(
'sourceAttribute' => 'eduPersonPrincipalName',
'targetAttribute' => 'scope',
);
$request = array(
'Attributes' => array(
'eduPersonPrincipalName' => array('johndoe'),
)
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayNotHasKey('scope', $attributes);
}
}
simplesamlphp-1.15.3/tests/modules/core/lib/Auth/Process/TargetedIDTest.php 0000644 0000000 0000000 00000016021 13245225037 025334 0 ustar root root process($request);
return $request;
}
// /**
// * Test the most basic functionality
// */
// public function testBasic()
// {
// $config = array(
// );
// $request = array(
// 'Attributes' => array(),
// 'UserID' => 'user2@example.org',
// );
// $result = self::processFilter($config, $request);
// $attributes = $result['Attributes'];
// $this->assertArrayHasKey('eduPersonTargetedID', $attributes);
// $this->assertRegExp('/^[0-9a-f]{40}$/', $attributes['eduPersonTargetedID'][0]);
// }
//
// /**
// * Test with src and dst entityIds.
// * Make sure to overwrite any present eduPersonTargetedId
// */
// public function testWithSrcDst()
// {
// $config = array(
// );
// $request = array(
// 'Attributes' => array(
// 'eduPersonTargetedID' => 'dummy',
// ),
// 'UserID' => 'user2@example.org',
// 'Source' => array(
// 'metadata-set' => 'saml20-idp-hosted',
// 'entityid' => 'urn:example:src:id',
// ),
// 'Destination' => array(
// 'metadata-set' => 'saml20-sp-remote',
// 'entityid' => 'joe',
// ),
// );
// $result = self::processFilter($config, $request);
// $attributes = $result['Attributes'];
// $this->assertArrayHasKey('eduPersonTargetedID', $attributes);
// $this->assertRegExp('/^[0-9a-f]{40}$/', $attributes['eduPersonTargetedID'][0]);
// }
//
// /**
// * Test with nameId config option set.
// */
// public function testNameIdGeneration()
// {
// $config = array(
// 'nameId' => true,
// );
// $request = array(
// 'Attributes' => array(
// ),
// 'UserID' => 'user2@example.org',
// 'Source' => array(
// 'metadata-set' => 'saml20-idp-hosted',
// 'entityid' => 'urn:example:src:id',
// ),
// 'Destination' => array(
// 'metadata-set' => 'saml20-sp-remote',
// 'entityid' => 'joe',
// ),
// );
// $result = self::processFilter($config, $request);
// $attributes = $result['Attributes'];
// $this->assertArrayHasKey('eduPersonTargetedID', $attributes);
// $this->assertRegExp('#^[0-9a-f]{40}$#', $attributes['eduPersonTargetedID'][0]);
// }
//
// /**
// * Test that Id is the same for subsequent invocations with same input.
// */
// public function testIdIsPersistent()
// {
// $config = array(
// );
// $request = array(
// 'Attributes' => array(
// 'eduPersonTargetedID' => 'dummy',
// ),
// 'UserID' => 'user2@example.org',
// 'Source' => array(
// 'metadata-set' => 'saml20-idp-hosted',
// 'entityid' => 'urn:example:src:id',
// ),
// 'Destination' => array(
// 'metadata-set' => 'saml20-sp-remote',
// 'entityid' => 'joe',
// ),
// );
// for ($i = 0; $i < 10; ++$i) {
// $result = self::processFilter($config, $request);
// $attributes = $result['Attributes'];
// $tid = $attributes['eduPersonTargetedID'][0];
// if (isset($prevtid)) {
// $this->assertEquals($prevtid, $tid);
// $prevtid = $tid;
// }
// }
// }
//
// /**
// * Test that Id is different for two different usernames and two different sp's
// */
// public function testIdIsUnique()
// {
// $config = array(
// );
// $request = array(
// 'Attributes' => array(
// ),
// 'UserID' => 'user2@example.org',
// 'Source' => array(
// 'metadata-set' => 'saml20-idp-hosted',
// 'entityid' => 'urn:example:src:id',
// ),
// 'Destination' => array(
// 'metadata-set' => 'saml20-sp-remote',
// 'entityid' => 'joe',
// ),
// );
// $result = self::processFilter($config, $request);
// $tid1 = $result['Attributes']['eduPersonTargetedID'][0];
//
// $request['UserID'] = 'user3@example.org';
// $result = self::processFilter($config, $request);
// $tid2 = $result['Attributes']['eduPersonTargetedID'][0];
//
// $this->assertNotEquals($tid1, $tid2);
//
// $request['Destination']['entityid'] = 'urn:example.org:another-sp';
// $result = self::processFilter($config, $request);
// $tid3 = $result['Attributes']['eduPersonTargetedID'][0];
//
// $this->assertNotEquals($tid2, $tid3);
// }
/**
* Test no userid set
*
* @expectedException Exception
*/
public function testNoUserID()
{
$config = array(
);
$request = array(
'Attributes' => array(),
);
$result = self::processFilter($config, $request);
}
/**
* Test with specified attribute not set
*
* @expectedException Exception
*/
public function testAttributeNotExists()
{
$config = array(
'attributename' => 'uid',
);
$request = array(
'Attributes' => array(
'displayName' => 'Jack Student',
),
);
$result = self::processFilter($config, $request);
}
/**
* Test with configuration error 1
*
* @expectedException Exception
*/
public function testConfigInvalidAttributeName()
{
$config = array(
'attributename' => 5,
);
$request = array(
'Attributes' => array(
'displayName' => 'Jack Student',
),
);
$result = self::processFilter($config, $request);
}
/**
* Test with configuration error 2
*
* @expectedException Exception
*/
public function testConfigInvalidNameId()
{
$config = array(
'nameId' => 'persistent',
);
$request = array(
'Attributes' => array(
'displayName' => 'Jack Student',
),
);
$result = self::processFilter($config, $request);
}
}
simplesamlphp-1.15.3/tests/modules/core/lib/Auth/Process/AttributeValueMapTest.php 0000644 0000000 0000000 00000016545 13245225037 026771 0 ustar root root process($request);
return $request;
}
/**
* Test the most basic functionality.
*
* @covers SimpleSAML\Module\core\Auth\Process\AttributeValueMap::__construct
* @covers SimpleSAML\Module\core\Auth\Process\AttributeValueMap::process
*/
public function testBasic()
{
$config = array(
'sourceattribute' => 'memberOf',
'targetattribute' => 'eduPersonAffiliation',
'values' => array(
'member' => array(
'theGroup',
'otherGroup',
),
),
);
$request = array(
'Attributes' => array(
'memberOf' => array('theGroup'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayNotHasKey('memberOf', $attributes);
$this->assertArrayHasKey('eduPersonAffiliation', $attributes);
$this->assertEquals($attributes['eduPersonAffiliation'], array('member'));
}
/**
* Test basic functionality, remove duplicates
*
* @covers SimpleSAML\Module\core\Auth\Process\AttributeValueMap::__construct
* @covers SimpleSAML\Module\core\Auth\Process\AttributeValueMap::process
*/
public function testNoDuplicates()
{
$config = array(
'sourceattribute' => 'memberOf',
'targetattribute' => 'eduPersonAffiliation',
'values' => array(
'member' => array(
'theGroup',
'otherGroup',
),
),
);
$request = array(
'Attributes' => array(
'memberOf' => array('theGroup', 'otherGroup'),
'eduPersonAffiliation' => array('member', 'someValue'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayNotHasKey('memberOf', $attributes);
$this->assertArrayHasKey('eduPersonAffiliation', $attributes);
$this->assertEquals($attributes['eduPersonAffiliation'], array('member', 'someValue'));
}
/**
* Test the %replace functionality.
*
* @covers SimpleSAML\Module\core\Auth\Process\AttributeValueMap::__construct
* @covers SimpleSAML\Module\core\Auth\Process\AttributeValueMap::process
*/
public function testReplace()
{
$config = array(
'sourceattribute' => 'memberOf',
'targetattribute' => 'eduPersonAffiliation',
'%replace',
'values' => array(
'member' => array(
'theGroup',
'otherGroup',
),
),
);
$request = array(
'Attributes' => array(
'memberOf' => array('theGroup'),
'eduPersonAffiliation' => array('someValue'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayNotHasKey('memberOf', $attributes);
$this->assertArrayHasKey('eduPersonAffiliation', $attributes);
$this->assertEquals($attributes['eduPersonAffiliation'], array('member'));
}
/**
* Test the %keep functionality.
*
* @covers SimpleSAML\Module\core\Auth\Process\AttributeValueMap::__construct
* @covers SimpleSAML\Module\core\Auth\Process\AttributeValueMap::process
*/
public function testKeep()
{
$config = array(
'sourceattribute' => 'memberOf',
'targetattribute' => 'eduPersonAffiliation',
'%keep',
'values' => array(
'member' => array(
'theGroup',
'otherGroup',
),
),
);
$request = array(
'Attributes' => array(
'memberOf' => array('theGroup'),
'eduPersonAffiliation' => array('someValue'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('memberOf', $attributes);
$this->assertArrayHasKey('eduPersonAffiliation', $attributes);
$this->assertEquals($attributes['eduPersonAffiliation'], array('someValue','member'));
}
/**
* Test unknown flag Exception
*
* @covers SimpleSAML\Module\core\Auth\Process\AttributeValueMap::__construct
* @covers SimpleSAML\Module\core\Auth\Process\AttributeValueMap::process
*/
public function testUnknownFlag()
{
$config = array(
'%test',
'targetattribute' => 'affiliation',
'sourceattribute' => 'memberOf',
'values' => array(
'member' => array(
'theGroup',
),
),
);
$request = array(
'Attributes' => array(
'memberOf' => array('theGroup'),
),
);
$result = self::processFilter($config, $request);
$this->assertArrayHasKey('affiliation', $result['Attributes']);
$this->assertArrayNotHasKey('memberOf', $result['Attributes']);
$this->assertContains('member', $result['Attributes']['affiliation']);
}
/**
* Test missing Source attribute
*
* @covers SimpleSAML\Module\core\Auth\Process\AttributeValueMap::__construct
* @covers SimpleSAML\Module\core\Auth\Process\AttributeValueMap::process
*
* @expectedException \Exception
*/
public function testMissingSourceAttribute()
{
$config = array(
'targetattribute' => 'affiliation',
'values' => array(
'member' => array(
'theGroup',
),
),
);
$request = array(
'Attributes' => array(
'memberOf' => array('theGroup'),
),
);
self::processFilter($config, $request);
}
/**
* Test missing Target attribute
*
* @covers SimpleSAML\Module\core\Auth\Process\AttributeValueMap::__construct
* @covers SimpleSAML\Module\core\Auth\Process\AttributeValueMap::process
*
* @expectedException \Exception
*/
public function testMissingTargetAttribute()
{
$config = array(
'sourceattribute' => 'memberOf',
'values' => array(
'member' => array(
'theGroup',
),
),
);
$request = array(
'Attributes' => array(
'memberOf' => array('theGroup'),
),
);
self::processFilter($config, $request);
}
}
simplesamlphp-1.15.3/tests/modules/core/lib/Auth/Process/ScopeAttributeTest.php 0000644 0000000 0000000 00000017501 13245225037 026321 0 ustar root root process($request);
return $request;
}
/*
* Test the most basic functionality.
*/
public function testBasic()
{
$config = array(
'scopeAttribute' => 'eduPersonPrincipalName',
'sourceAttribute' => 'eduPersonAffiliation',
'targetAttribute' => 'eduPersonScopedAffiliation',
);
$request = array(
'Attributes' => array(
'eduPersonPrincipalName' => array('jdoe@example.com'),
'eduPersonAffiliation' => array('member'),
)
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('eduPersonScopedAffiliation', $attributes);
$this->assertEquals($attributes['eduPersonScopedAffiliation'], array('member@example.com'));
}
/*
* If target attribute already set, module must add, not overwrite.
*/
public function testNoOverwrite()
{
$config = array(
'scopeAttribute' => 'eduPersonPrincipalName',
'sourceAttribute' => 'eduPersonAffiliation',
'targetAttribute' => 'eduPersonScopedAffiliation',
);
$request = array(
'Attributes' => array(
'eduPersonPrincipalName' => array('jdoe@example.com'),
'eduPersonAffiliation' => array('member'),
'eduPersonScopedAffiliation' => array('library-walk-in@example.edu'),
)
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['eduPersonScopedAffiliation'], array('library-walk-in@example.edu', 'member@example.com'));
}
/*
* If same scope already set, module must do nothing, not duplicate value.
*/
public function testNoDuplication()
{
$config = array(
'scopeAttribute' => 'eduPersonPrincipalName',
'sourceAttribute' => 'eduPersonAffiliation',
'targetAttribute' => 'eduPersonScopedAffiliation',
);
$request = array(
'Attributes' => array(
'eduPersonPrincipalName' => array('jdoe@example.com'),
'eduPersonAffiliation' => array('member'),
'eduPersonScopedAffiliation' => array('member@example.com'),
)
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['eduPersonScopedAffiliation'], array('member@example.com'));
}
/*
* If source attribute not set, nothing happens
*/
public function testNoSourceAttribute()
{
$config = array(
'scopeAttribute' => 'eduPersonPrincipalName',
'sourceAttribute' => 'eduPersonAffiliation',
'targetAttribute' => 'eduPersonScopedAffiliation',
);
$request = array(
'Attributes' => array(
'mail' => array('j.doe@example.edu', 'john@example.org'),
'eduPersonAffiliation' => array('member'),
'eduPersonScopedAffiliation' => array('library-walk-in@example.edu'),
)
);
$result = self::processFilter($config, $request);
$this->assertEquals($request['Attributes'], $result['Attributes']);
}
/*
* If scope attribute not set, nothing happens
*/
public function testNoScopeAttribute()
{
$config = array(
'scopeAttribute' => 'eduPersonPrincipalName',
'sourceAttribute' => 'eduPersonAffiliation',
'targetAttribute' => 'eduPersonScopedAffiliation',
);
$request = array(
'Attributes' => array(
'mail' => array('j.doe@example.edu', 'john@example.org'),
'eduPersonScopedAffiliation' => array('library-walk-in@example.edu'),
'eduPersonPrincipalName' => array('jdoe@example.com'),
)
);
$result = self::processFilter($config, $request);
$this->assertEquals($request['Attributes'], $result['Attributes']);
}
/*
* When multiple @ signs in attribute, will use the first one.
*/
public function testMultiAt()
{
$config = array(
'scopeAttribute' => 'eduPersonPrincipalName',
'sourceAttribute' => 'eduPersonAffiliation',
'targetAttribute' => 'eduPersonScopedAffiliation',
);
$request = array(
'Attributes' => array(
'eduPersonPrincipalName' => array('john@doe@example.com'),
'eduPersonAffiliation' => array('member'),
)
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['eduPersonScopedAffiliation'], array('member@doe@example.com'));
}
/*
* When multiple values in source attribute, should render multiple targets.
*/
public function testMultivaluedSource()
{
$config = array(
'scopeAttribute' => 'eduPersonPrincipalName',
'sourceAttribute' => 'eduPersonAffiliation',
'targetAttribute' => 'eduPersonScopedAffiliation',
);
$request = array(
'Attributes' => array(
'eduPersonPrincipalName' => array('jdoe@example.com'),
'eduPersonAffiliation' => array('member','staff','faculty'),
)
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['eduPersonScopedAffiliation'], array('member@example.com','staff@example.com','faculty@example.com'));
}
/*
* When the source attribute doesn't have a scope, the entire value is used.
*/
public function testNoAt()
{
$config = array(
'scopeAttribute' => 'schacHomeOrganization',
'sourceAttribute' => 'eduPersonAffiliation',
'targetAttribute' => 'eduPersonScopedAffiliation',
);
$request = array(
'Attributes' => array(
'schacHomeOrganization' => array('example.org'),
'eduPersonAffiliation' => array('student'),
)
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['eduPersonScopedAffiliation'], array('student@example.org'));
}
/*
* When the target attribute exists and onlyIfEmpty is set
*/
public function testOnlyIfEmpty()
{
$config = array(
'scopeAttribute' => 'schacHomeOrganization',
'sourceAttribute' => 'eduPersonAffiliation',
'targetAttribute' => 'eduPersonScopedAffiliation',
'onlyIfEmpty' => true,
);
$request = array(
'Attributes' => array(
'schacHomeOrganization' => array('example.org'),
'eduPersonAffiliation' => array('student'),
'eduPersonScopedAffiliation' => array('staff@example.org', 'member@example.org'),
)
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['eduPersonScopedAffiliation'], array('staff@example.org', 'member@example.org'));
}
}
simplesamlphp-1.15.3/tests/modules/core/lib/Auth/Process/AttributeCopyTest.php 0000644 0000000 0000000 00000011363 13245225037 026162 0 ustar root root process($request);
return $request;
}
/**
* Test the most basic functionality.
*/
public function testBasic()
{
$config = array(
'test' => 'testnew',
);
$request = array(
'Attributes' => array('test' => array('AAP')),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('test', $attributes);
$this->assertArrayHasKey('testnew', $attributes);
$this->assertEquals($attributes['testnew'], array('AAP'));
}
/**
* Test the most basic functionality.
*/
public function testArray()
{
$config = array(
'test' => array('new1','new2'),
);
$request = array(
'Attributes' => array('test' => array('AAP')),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('test', $attributes);
$this->assertArrayHasKey('new1', $attributes);
$this->assertArrayHasKey('new2', $attributes);
$this->assertEquals($attributes['new1'], array('AAP'));
$this->assertEquals($attributes['new2'], array('AAP'));
}
/**
* Test that existing attributes are left unmodified.
*/
public function testExistingNotModified()
{
$config = array(
'test' => 'testnew',
);
$request = array(
'Attributes' => array(
'test' => array('AAP'),
'original1' => array('original_value1'),
'original2' => array('original_value2'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('testnew', $attributes);
$this->assertEquals($attributes['test'], array('AAP'));
$this->assertArrayHasKey('original1', $attributes);
$this->assertEquals($attributes['original1'], array('original_value1'));
$this->assertArrayHasKey('original2', $attributes);
$this->assertEquals($attributes['original2'], array('original_value2'));
}
/**
* Test copying multiple attributes
*/
public function testCopyMultiple()
{
$config = array(
'test1' => 'new1',
'test2' => 'new2',
);
$request = array(
'Attributes' => array('test1' => array('val1'), 'test2' => array('val2.1','val2.2')),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('new1', $attributes);
$this->assertEquals($attributes['new1'], array('val1'));
$this->assertArrayHasKey('new2', $attributes);
$this->assertEquals($attributes['new2'], array('val2.1','val2.2'));
}
/**
* Test behaviour when target attribute exists (should be replaced).
*/
public function testCopyClash()
{
$config = array(
'test' => 'new1',
);
$request = array(
'Attributes' => array(
'test' => array('testvalue1'),
'new1' => array('newvalue1'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['new1'], array('testvalue1'));
}
/**
* Test wrong attribute name
*
* @expectedException Exception
*/
public function testWrongAttributeName()
{
$config = array(
array('value2'),
);
$request = array(
'Attributes' => array(
'test' => array('value1'),
),
);
$result = self::processFilter($config, $request);
}
/**
* Test wrong attribute value
*
* @expectedException Exception
*/
public function testWrongAttributeValue()
{
$config = array(
'test' => 100,
);
$request = array(
'Attributes' => array(
'test' => array('value1'),
),
);
$result = self::processFilter($config, $request);
}
}
simplesamlphp-1.15.3/tests/modules/core/lib/Auth/Process/AttributeAddTest.php 0000644 0000000 0000000 00000011711 13245225037 025735 0 ustar root root process($request);
return $request;
}
/**
* Test the most basic functionality.
*/
public function testBasic()
{
$config = array(
'test' => array('value1', 'value2'),
);
$request = array(
'Attributes' => array(),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('test', $attributes);
$this->assertEquals($attributes['test'], array('value1', 'value2'));
}
/**
* Test that existing attributes are left unmodified.
*/
public function testExistingNotModified()
{
$config = array(
'test' => array('value1', 'value2'),
);
$request = array(
'Attributes' => array(
'original1' => array('original_value1'),
'original2' => array('original_value2'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('test', $attributes);
$this->assertEquals($attributes['test'], array('value1', 'value2'));
$this->assertArrayHasKey('original1', $attributes);
$this->assertEquals($attributes['original1'], array('original_value1'));
$this->assertArrayHasKey('original2', $attributes);
$this->assertEquals($attributes['original2'], array('original_value2'));
}
/**
* Test single string as attribute value.
*/
public function testStringValue()
{
$config = array(
'test' => 'value',
);
$request = array(
'Attributes' => array(),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('test', $attributes);
$this->assertEquals($attributes['test'], array('value'));
}
/**
* Test adding multiple attributes in one config.
*/
public function testAddMultiple()
{
$config = array(
'test1' => array('value1'),
'test2' => array('value2'),
);
$request = array(
'Attributes' => array(),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('test1', $attributes);
$this->assertEquals($attributes['test1'], array('value1'));
$this->assertArrayHasKey('test2', $attributes);
$this->assertEquals($attributes['test2'], array('value2'));
}
/**
* Test behavior when appending attribute values.
*/
public function testAppend()
{
$config = array(
'test' => array('value2'),
);
$request = array(
'Attributes' => array(
'test' => array('value1'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['test'], array('value1', 'value2'));
}
/**
* Test replacing attribute values.
*/
public function testReplace()
{
$config = array(
'%replace',
'test' => array('value2'),
);
$request = array(
'Attributes' => array(
'test' => array('value1'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['test'], array('value2'));
}
/**
* Test wrong usage generates exceptions
*
* @expectedException Exception
*/
public function testWrongFlag()
{
$config = array(
'%nonsense',
'test' => array('value2'),
);
$request = array(
'Attributes' => array(
'test' => array('value1'),
),
);
$result = self::processFilter($config, $request);
}
/**
* Test wrong attribute value
*
* @expectedException Exception
*/
public function testWrongAttributeValue()
{
$config = array(
'%replace',
'test' => array(true),
);
$request = array(
'Attributes' => array(
'test' => array('value1'),
),
);
$result = self::processFilter($config, $request);
}
}
simplesamlphp-1.15.3/tests/modules/core/lib/Auth/Process/PHPTest.php 0000644 0000000 0000000 00000002515 13245225037 024012 0 ustar root root process($request);
return $request;
}
/**
* Test the configuration of the filter.
*
* @expectedException SimpleSAML_Error_Exception
*/
public function testInvalidConfiguration()
{
$config = array();
new sspmod_core_Auth_Process_PHP($config, null);
}
/**
* Check that defining the code works as expected.
*/
public function testCodeDefined()
{
$config = array(
'code' => '
$attributes["key"] = "value";
',
);
$request = array('Attributes' => array());
$expected = array(
'Attributes' => array(
'key' => 'value',
),
);
$this->assertEquals($expected, $this->processFilter($config, $request));
}
}
simplesamlphp-1.15.3/tests/modules/core/lib/Auth/Process/AttributeRealmTest.php 0000644 0000000 0000000 00000007477 13245225037 026323 0 ustar root root process($request);
return $request;
}
/**
* Test the most basic functionality.
*/
public function testBasic()
{
$config = array(
);
$request = array(
'Attributes' => array(),
'UserID' => 'user2@example.org',
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('realm', $attributes);
$this->assertEquals($attributes['realm'], array('example.org'));
}
/**
* Test no userid set
*
* @expectedException Exception
*/
public function testNoUserID()
{
$config = array(
);
$request = array(
'Attributes' => array(),
);
$result = self::processFilter($config, $request);
}
/**
* Test with configuration.
*/
public function testAttributeNameConfig()
{
$config = array(
'attributename' => 'schacHomeOrganization',
);
$request = array(
'Attributes' => array(
'displayName' => 'Joe User',
'schacGender' => 9,
),
'UserID' => 'user2@example.org',
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('schacHomeOrganization', $attributes);
$this->assertArrayHasKey('displayName', $attributes);
$this->assertEquals($attributes['schacHomeOrganization'], array('example.org'));
}
/**
* When target attribute exists it will be overwritten
*/
public function testTargetAttributeOverwritten()
{
$config = array(
'attributename' => 'schacHomeOrganization',
);
$request = array(
'Attributes' => array(
'displayName' => 'Joe User',
'schacGender' => 9,
'schacHomeOrganization' => 'example.com',
),
'UserID' => 'user2@example.org',
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('schacHomeOrganization', $attributes);
$this->assertEquals($attributes['schacHomeOrganization'], array('example.org'));
}
/**
* When source attribute has no "@" no realm is added
*/
public function testNoAtisNoOp()
{
$config = array();
$request = array(
'Attributes' => array(
'displayName' => 'Joe User',
),
'UserID' => 'user2',
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayNotHasKey('realm', $attributes);
}
/**
* When source attribute has more than one "@" no realm is added
*/
public function testMultiAtisNoOp()
{
$config = array();
$request = array(
'Attributes' => array(
'displayName' => 'Joe User',
),
'UserID' => 'user2@home@example.org',
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayNotHasKey('realm', $attributes);
}
}
simplesamlphp-1.15.3/tests/modules/core/lib/Auth/Process/AttributeAlterTest.php 0000644 0000000 0000000 00000023161 13245225037 026316 0 ustar root root process($request);
return $request;
}
/**
* Test the most basic functionality.
*/
public function testBasic()
{
$config = array(
'subject' => 'test',
'pattern' => '/wrong/',
'replacement' => 'right',
);
$request = array(
'Attributes' => array(
'test' => array('somethingiswrong'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('test', $attributes);
$this->assertEquals($attributes['test'], array('somethingisright'));
}
/**
* Test the most basic functionality.
*/
public function testWithTarget()
{
$config = array(
'subject' => 'test',
'target' => 'test2',
'pattern' => '/wrong/',
'replacement' => 'right',
);
$request = array(
'Attributes' => array(
'something' => array('somethingelse'),
'test' => array('wrong'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('test2', $attributes);
$this->assertEquals($attributes['test'], array('wrong'));
$this->assertEquals($attributes['test2'], array('right'));
}
/**
* Module is a no op if subject attribute is not present.
*/
public function testNomatch()
{
$config = array(
'subject' => 'test',
'pattern' => '/wrong/',
'replacement' => 'right',
);
$request = array(
'Attributes' => array(
'something' => array('somevalue'),
'somethingelse' => array('someothervalue'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes,
array('something' => array('somevalue'),
'somethingelse' => array('someothervalue')));
}
/**
* Test replacing attribute value.
*/
public function testReplaceMatch()
{
$config = array(
'subject' => 'source',
'pattern' => '/wrong/',
'replacement' => 'right',
'%replace',
);
$request = array(
'Attributes' => array(
'source' => array('wrongthing'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['source'], array('right'));
}
/**
* Test replacing attribute value.
*/
public function testReplaceMatchWithTarget()
{
$config = array(
'subject' => 'source',
'pattern' => '/wrong/',
'replacement' => 'right',
'target' => 'test',
'%replace',
);
$request = array(
'Attributes' => array(
'source' => array('wrong'),
'test' => array('wrong'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['test'], array('right'));
}
/**
* Test replacing attribute values.
*/
public function testReplaceNoMatch()
{
$config = array(
'subject' => 'test',
'pattern' => '/doink/',
'replacement' => 'wrong',
'target' => 'test',
'%replace',
);
$request = array(
'Attributes' => array(
'source' => array('wrong'),
'test' => array('right'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['test'], array('right'));
}
/**
* Test removing attribute values.
* Note that removing a value does not renumber the attributes array.
* Also ensure unrelated attributes are not touched.
*/
public function testRemoveMatch()
{
$config = array(
'subject' => 'eduPersonAffiliation',
'pattern' => '/^emper/',
'%remove',
);
$request = array(
'Attributes' => array(
'displayName' => array('emperor kuzco'),
'eduPersonAffiliation' => array('member', 'emperor', 'staff'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertEquals($attributes['displayName'], array('emperor kuzco'));
$this->assertEquals($attributes['eduPersonAffiliation'], array(0 => 'member', 2 => 'staff'));
}
/**
* Test removing attribute values, resulting in an empty attribute.
*/
public function testRemoveMatchAll()
{
$config = array(
'subject' => 'eduPersonAffiliation',
'pattern' => '/^emper/',
'%remove',
);
$request = array(
'Attributes' => array(
'displayName' => array('emperor kuzco'),
'eduPersonAffiliation' => array('emperess', 'emperor'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayNotHasKey('eduPersonAffiliation', $attributes);
}
/**
* Test for exception with illegal config.
*
* @expectedException Exception
*/
public function testWrongConfig()
{
$config = array(
'subject' => 'eduPersonAffiliation',
'pattern' => '/^emper/',
'%dwiw',
);
$request = array(
'Attributes' => array(
'eduPersonAffiliation' => array('emperess', 'emperor'),
),
);
$result = self::processFilter($config, $request);
}
/**
* Test for exception with illegal config.
*
* @expectedException Exception
*/
public function testIncompleteConfig()
{
$config = array(
'subject' => 'eduPersonAffiliation',
);
$request = array(
'Attributes' => array(
'eduPersonAffiliation' => array('emperess', 'emperor'),
),
);
$result = self::processFilter($config, $request);
}
/**
* Test for exception with illegal config.
*
* @expectedException Exception
*/
public function testIncompleteConfig2()
{
$config = array(
'subject' => 'test',
'pattern' => '/wrong/',
);
$request = array(
'Attributes' => array(
'test' => array('somethingiswrong'),
),
);
$request = array(
'Attributes' => array(
'eduPersonAffiliation' => array('emperess', 'emperor'),
),
);
$result = self::processFilter($config, $request);
}
/**
* Test for exception with illegal config.
*
* @expectedException Exception
*/
public function testIncompleteConfig3()
{
$config = array(
'subject' => 'test',
'pattern' => '/wrong/',
'%replace',
'%remove',
);
$request = array(
'Attributes' => array(
'test' => array('somethingiswrong'),
),
);
$request = array(
'Attributes' => array(
'eduPersonAffiliation' => array('emperess', 'emperor'),
),
);
$result = self::processFilter($config, $request);
}
/**
* Test for exception with illegal config.
*
* @expectedException Exception
*/
public function testIncompleteConfig4()
{
$config = array(
'subject' => 'test',
'pattern' => '/wrong/',
'target' => 'test2',
'%remove',
);
$request = array(
'Attributes' => array(
'test' => array('somethingiswrong'),
),
);
$request = array(
'Attributes' => array(
'eduPersonAffiliation' => array('emperess', 'emperor'),
),
);
$result = self::processFilter($config, $request);
}
/**
* Test for exception with illegal config.
*
* @expectedException Exception
*/
public function testIncompleteConfig5()
{
$config = array(
'subject' => 'test',
'pattern' => '/wrong/',
'replacement' => null,
);
$request = array(
'Attributes' => array(
'test' => array('somethingiswrong'),
),
);
$request = array(
'Attributes' => array(
'eduPersonAffiliation' => array('emperess', 'emperor'),
),
);
$result = self::processFilter($config, $request);
}
}
simplesamlphp-1.15.3/tests/modules/core/lib/Auth/Process/AttributeLimitTest.php 0000644 0000000 0000000 00000023652 13245225037 026332 0 ustar root root process($request);
return $request;
}
/**
* Test reading IdP Attributes.
*/
public function testIdPAttrs()
{
$config = array(
'cn', 'mail'
);
$request = array(
'Attributes' => array(
'eduPersonTargetedID' => array('eptid@example.org'),
'eduPersonAffiliation' => array('member'),
'cn' => array('user name'),
'mail' => array('user@example.org'),
),
'Destination' => array(
),
'Source' => array(
'attributes' => array('cn','mail'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('cn', $attributes);
$this->assertArrayHasKey('mail', $attributes);
$this->assertArrayNotHasKey('eduPersonTargetedID', $attributes);
$this->assertArrayNotHasKey('eduPersonAffiliation', $attributes);
$this->assertCount(2, $attributes);
$config = array(
'cn',
'default' => TRUE,
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('cn', $attributes);
$this->assertArrayHasKey('mail', $attributes);
$this->assertArrayNotHasKey('eduPersonTargetedID', $attributes);
$this->assertArrayNotHasKey('eduPersonAffiliation', $attributes);
$this->assertCount(2, $attributes);
}
/**
* Tests when no attributes are in metadata.
*/
public function testNULLMetadataAttrs()
{
$config = array(
'cn', 'mail'
);
$request = array(
'Attributes' => array(
'eduPersonTargetedID' => array('eptid@example.org'),
'eduPersonAffiliation' => array('member'),
'cn' => array('user name'),
'mail' => array('user@example.org'),
),
'Destination' => array(
),
'Source' => array(
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('cn', $attributes);
$this->assertArrayHasKey('mail', $attributes);
$this->assertArrayNotHasKey('eduPersonTargetedID', $attributes);
$this->assertArrayNotHasKey('eduPersonAffiliation', $attributes);
$this->assertCount(2, $attributes);
$config = array(
'cn',
'default' => TRUE,
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('cn', $attributes);
$this->assertArrayNotHasKey('mail', $attributes);
$this->assertArrayNotHasKey('eduPersonTargetedID', $attributes);
$this->assertArrayNotHasKey('eduPersonAffiliation', $attributes);
$this->assertCount(1, $attributes);
$config = array(
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertCount(4, $attributes);
$this->assertArrayHasKey('eduPersonTargetedID', $attributes);
$this->assertArrayHasKey('eduPersonAffiliation', $attributes);
$this->assertArrayHasKey('cn', $attributes);
$this->assertArrayHasKey('mail', $attributes);
}
/**
* setUpBeforeClass a request that will be used for the following tests.
* note the above tests don't use self::$request for processFilter input.
*/
protected static $request;
public static function setUpBeforeClass()
{
self::$request = array(
'Attributes' => array(
'eduPersonTargetedID' => array('eptid@example.org'),
'eduPersonAffiliation' => array('member'),
'cn' => array('common name'),
'mail' => array('user@example.org'),
),
'Destination' => array(
'attributes' => array('cn','mail'),
),
'Source' => array(
),
);
}
/**
* Test the most basic functionality.
*/
public function testBasic()
{
$config = array(
'cn', 'mail'
);
$result = self::processFilter($config, self::$request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('cn', $attributes);
$this->assertArrayHasKey('mail', $attributes);
$this->assertCount(2, $attributes);
}
/**
* Test defaults with metadata available.
*/
public function testDefaultWithMetadata()
{
$config = array(
'default' => TRUE,
);
$result = self::processFilter($config, self::$request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('cn', $attributes);
$this->assertArrayHasKey('mail', $attributes);
$this->assertCount(2, $attributes);
}
/**
* Test defaults with attributes and metadata
*/
public function testDefaultWithAttrs()
{
$config = array(
'default' => TRUE,
'eduPersonTargetedID', 'eduPersonAffiliation',
);
$result = self::processFilter($config, self::$request);
$attributes = $result['Attributes'];
$this->assertCount(2, $attributes);
$this->assertArrayHasKey('cn', $attributes);
$this->assertArrayHasKey('mail', $attributes);
$this->assertArrayNotHasKey('eduPersonTargetedID', $attributes);
$this->assertArrayNotHasKey('eduPersonAffiliation', $attributes);
}
/**
* Test for exception with illegal config.
*
* @expectedException Exception
*/
public function testInvalidConfig()
{
$config = array(
'invalidArg' => TRUE,
);
$result = self::processFilter($config, self::$request);
}
/**
* Test for invalid attribute name
*
* @expectedException Exception
*/
public function testInvalidAttributeName()
{
$config = array(
null
);
$result = self::processFilter($config, self::$request);
}
/**
* Test for attribute value matching
*/
public function testMatchAttributeValues()
{
$config = array(
'eduPersonAffiliation' => array('member')
);
$result = self::processFilter($config, self::$request);
$attributes = $result['Attributes'];
$this->assertCount(1, $attributes);
$this->assertArrayHasKey('eduPersonAffiliation', $attributes);
$this->assertEquals($attributes['eduPersonAffiliation'], array('member'));
$config = array(
'eduPersonAffiliation' => array('member','staff')
);
$result = self::processFilter($config, self::$request);
$attributes = $result['Attributes'];
$this->assertCount(1, $attributes);
$this->assertArrayHasKey('eduPersonAffiliation', $attributes);
$this->assertEquals($attributes['eduPersonAffiliation'], array('member'));
$config = array(
'eduPersonAffiliation' => array('student')
);
$result = self::processFilter($config, self::$request);
$attributes = $result['Attributes'];
$this->assertCount(0, $attributes);
$config = array(
'eduPersonAffiliation' => array('student','staff')
);
$result = self::processFilter($config, self::$request);
$attributes = $result['Attributes'];
$this->assertCount(0, $attributes);
}
/**
* Test for allowed attributes not an array.
*
* This test is very unlikely and would require malformed metadata processing.
* Cannot be generated via config options.
*
* @expectedException Exception
*/
public function testMatchAttributeValuesNotArray()
{
$config = array(
);
$request = array(
'Attributes' => array(
'eduPersonTargetedID' => array('eptid@example.org'),
'eduPersonAffiliation' => array('member'),
'cn' => array('user name'),
'mail' => array('user@example.org'),
'discardme' => array('somethingiswrong'),
),
'Destination' => array(
'attributes' => array('eduPersonAffiliation' => 'student'),
),
'Source' => array(
),
);
$result = self::processFilter($config, $request);
}
/**
* Test attributes not intersecting
*/
public function testNoIntersection()
{
$config = array(
'default' => TRUE,
);
$request = array(
'Attributes' => array(
'eduPersonTargetedID' => array('eptid@example.org'),
'eduPersonAffiliation' => array('member'),
'cn' => array('user name'),
'mail' => array('user@example.org'),
'discardme' => array('somethingiswrong'),
),
'Destination' => array(
'attributes' => array('urn:oid:1.2.840.113549.1.9.1'),
),
'Source' => array(
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertCount(0, $attributes);
$this->assertEmpty($attributes);
}
}
simplesamlphp-1.15.3/tests/modules/consent/ 0000755 0000000 0000000 00000000000 13245225037 017443 5 ustar root root simplesamlphp-1.15.3/tests/modules/consent/lib/ 0000755 0000000 0000000 00000000000 13245225037 020211 5 ustar root root simplesamlphp-1.15.3/tests/modules/consent/lib/Auth/ 0000755 0000000 0000000 00000000000 13245225037 021112 5 ustar root root simplesamlphp-1.15.3/tests/modules/consent/lib/Auth/Process/ 0000755 0000000 0000000 00000000000 13245225037 022530 5 ustar root root simplesamlphp-1.15.3/tests/modules/consent/lib/Auth/Process/ConsentTest.php 0000644 0000000 0000000 00000011556 13245225037 025522 0 ustar root root
* @package SimpleSAMLphp
*/
namespace SimpleSAML\Test\Module\consent\Auth\Process;
use \SimpleSAML_Configuration as Configuration;
class ConsentTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->config = Configuration::loadFromArray(array(), '[ARRAY]', 'simplesaml');
}
/**
* Helper function to run the filter with a given configuration.
*
* @param array $config The filter configuration.
* @param array $request The request state.
* @return array The state array after processing.
*/
private function processFilter(array $config, array $request)
{
$filter = new \sspmod_consent_Auth_Process_Consent($config, null);
$filter->process($request);
return $request;
}
/**
* Test for the private checkDisable() method.
*/
public function testCheckDisable()
{
// test consent disable regex with match
$config = array();
// test consent disable with match on specific SP entityid
$request = array(
'Source' => array(
'entityid' => 'https://idp.example.org',
'metadata-set' => 'saml20-idp-local',
'consent.disable' => array(
'https://valid.flatstring.example.that.does.not.match',
),
'SingleSignOnService' => array(
array(
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'Location' => 'https://idp.example.org/saml2/idp/SSOService.php',
),
),
),
'Destination' => array(
// valid entityid equal to the last one in the consent.disable array
'entityid' => 'https://sp.example.org/my-sp',
'metadata-set' => 'saml20-sp-remote',
'consent.disable' => array(
array('type' => 'regex', 'pattern' => '/invalid/i'),
'https://sp.example.org/my-sp', // accept the SP that has this specific entityid
'https://idp.example.org',
),
),
'UserID' => 'jdoe',
'Attributes' => array(
'eduPersonPrincipalName' => array('jdoe@example.com'),
),
);
$result = $this->processFilter($config, $request);
// the state should NOT have changed because NO consent should be necessary (match)
$this->assertEquals($request, $result);
// test consent disable with match on SP through regular expression
$request = array(
'Source' => array(
'entityid' => 'https://idp.example.org',
'metadata-set' => 'saml20-idp-local',
'consent.disable' => array(
array(), // invalid consent option array should be ignored
1234, // bad option
array(''), // no type
array('type'=>'invalid'), // invalid consent option type should be ignored
array('type'=>'regex'), // regex consent option without pattern should be ignored
array('type'=>'regex', 'pattern'=>'/.*\.valid.regex\.that\.does\.not\.match.*/i'),
// accept any SP that has an entityid that contains the string ".example.org"
array('type'=>'regex', 'pattern'=>'/.*\.example\.org\/.*/i'),
),
'SingleSignOnService' => array(
array(
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'Location' => 'https://idp.example.org/saml2/idp/SSOService.php',
),
),
),
'Destination' => array(
'entityid' => 'https://sp.example.org/my-sp', // sp contains the string ".example.org"
'metadata-set' => 'saml20-sp-remote',
),
'UserID' => 'jdoe',
'Attributes' => array(
'eduPersonPrincipalName' => array('jdoe@example.com'),
),
);
$result = $this->processFilter($config, $request);
// the state should NOT have changed because NO consent should be necessary (match)
$this->assertEquals($request, $result);
// test corner cases
$request['Source']['consent.disable'] = array(
'https://valid.flatstring.example.that.does.not.match',
array('foo' => 'bar'),
);
$request['Destination']['consent.disable'] = 1;
$result = $this->processFilter($config, $request);
// the state should NOT have changed because NO consent should be necessary (match)
$this->assertEquals($request, $result);
}
}
simplesamlphp-1.15.3/tests/modules/saml/ 0000755 0000000 0000000 00000000000 13245225037 016726 5 ustar root root simplesamlphp-1.15.3/tests/modules/saml/lib/ 0000755 0000000 0000000 00000000000 13245225037 017474 5 ustar root root simplesamlphp-1.15.3/tests/modules/saml/lib/Auth/ 0000755 0000000 0000000 00000000000 13245225037 020375 5 ustar root root simplesamlphp-1.15.3/tests/modules/saml/lib/Auth/Process/ 0000755 0000000 0000000 00000000000 13245225037 022013 5 ustar root root simplesamlphp-1.15.3/tests/modules/saml/lib/Auth/Process/NameIDAttributeTest.php 0000644 0000000 0000000 00000007745 13245225037 026362 0 ustar root root
* @package SimpleSAMLphp
*/
use PHPUnit\Framework\TestCase;
class NameIDAttributeTest extends TestCase
{
/*
* Helper function to run the filter with a given configuration.
*
* @param array $config The filter configuration.
* @param array $request The request state.
* @return array The state array after processing.
*/
private function processFilter(array $config, array $request)
{
$filter = new sspmod_saml_Auth_Process_NameIDAttribute($config, null);
$filter->process($request);
return $request;
}
/**
* Test minimal configuration.
*/
public function testMinimalConfig()
{
$config = array();
$nameId = new \SAML2\XML\saml\NameID();
$nameId->value = 'eugene@oombaas';
$nameId->Format = \SAML2\Constants::NAMEID_PERSISTENT;
$spId = 'eugeneSP';
$idpId = 'eugeneIdP';
$request = array(
'Source' => array(
'entityid' => $spId,
),
'Destination' => array(
'entityid' => $idpId,
),
'saml:sp:NameID' => $nameId,
);
$result = $this->processFilter($config, $request);
$this->assertEquals("{$spId}!{$idpId}!{$nameId->value}", $result['Attributes']['nameid'][0]);
}
/**
* Test custom attribute name.
*/
public function testCustomAttributeName()
{
$attributeName = 'eugeneNameIDAttribute';
$config = array('attribute' => $attributeName);
$nameId = new \SAML2\XML\saml\NameID();
$nameId->value = 'eugene@oombaas';
$nameId->Format = \SAML2\Constants::NAMEID_PERSISTENT;
$spId = 'eugeneSP';
$idpId = 'eugeneIdP';
$request = array(
'Source' => array(
'entityid' => $spId,
),
'Destination' => array(
'entityid' => $idpId,
),
'saml:sp:NameID' => $nameId,
);
$result = $this->processFilter($config, $request);
$this->assertTrue(isset($result['Attributes'][$attributeName]));
$this->assertEquals("{$spId}!{$idpId}!{$nameId->value}", $result['Attributes'][$attributeName][0]);
}
/**
* Test custom format.
*/
public function testFormat()
{
$config = array('format' => '%V');
$nameId = new \SAML2\XML\saml\NameID();
$nameId->value = 'eugene@oombaas';
$nameId->Format = \SAML2\Constants::NAMEID_PERSISTENT;
$spId = 'eugeneSP';
$idpId = 'eugeneIdP';
$request = array(
'Source' => array(
'entityid' => $spId,
),
'Destination' => array(
'entityid' => $idpId,
),
'saml:sp:NameID' => $nameId,
);
$result = $this->processFilter($config, $request);
$this->assertEquals("{$nameId->value}", $result['Attributes']['nameid'][0]);
}
/**
* Test custom attribute name with format.
*/
public function testCustomAttributeNameAndFormat()
{
$attributeName = 'eugeneNameIDAttribute';
$config = array('attribute' => $attributeName, 'format' => '%V');
$nameId = new \SAML2\XML\saml\NameID();
$nameId->value = 'eugene@oombaas';
$nameId->Format = \SAML2\Constants::NAMEID_PERSISTENT;
$spId = 'eugeneSP';
$idpId = 'eugeneIdP';
$request = array(
'Source' => array(
'entityid' => $spId,
),
'Destination' => array(
'entityid' => $idpId,
),
'saml:sp:NameID' => $nameId,
);
$result = $this->processFilter($config, $request);
$this->assertTrue(isset($result['Attributes'][$attributeName]));
$this->assertEquals("{$nameId->value}", $result['Attributes'][$attributeName][0]);
}
}
simplesamlphp-1.15.3/tests/modules/saml/lib/Auth/Process/FilterScopesTest.php 0000644 0000000 0000000 00000010640 13245225037 025767 0 ustar root root
* @package SimpleSAMLphp
*/
namespace SimpleSAML\Test\Module\saml\Auth\Process;
class FilterScopesTest extends \PHPUnit_Framework_TestCase
{
/*
* Helper function to run the filter with a given configuration.
*
* @param array $config The filter configuration.
* @param array $request The request state.
* @return array The state array after processing.
*/
private function processFilter(array $config, array $request)
{
$filter = new \SimpleSAML\Module\saml\Auth\Process\FilterScopes($config, null);
$filter->process($request);
return $request;
}
/**
* Test valid scopes.
*/
public function testValidScopes()
{
// test declared scopes
$config = array();
$request = array(
'Source' => array(
'SingleSignOnService' => array(
array(
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'Location' => 'https://example.org/saml2/idp/SSOService.php',
),
),
'scope' => array(
'example.com',
'example.net',
),
),
'Attributes' => array(
'eduPersonPrincipalName' => array('jdoe@example.com'),
),
);
$result = $this->processFilter($config, $request);
$this->assertEquals($request['Attributes'], $result['Attributes']);
// test multiple values
$request['Attributes'] = array(
'eduPersonPrincipalName' => array(
'jdoe@example.com',
'jdoe@example.net',
),
);
$result = $this->processFilter($config, $request);
$this->assertEquals($request['Attributes'], $result['Attributes']);
// test implicit scope
$request['Attributes'] = array(
'eduPersonPrincipalName' => array('jdoe@example.org'),
);
$result = $this->processFilter($config, $request);
$this->assertEquals($request['Attributes'], $result['Attributes']);
// test alternative attributes
$config['attributes'] = array(
'mail',
);
$request['Attributes'] = array(
'mail' => array('john.doe@example.org'),
);
$result = $this->processFilter($config, $request);
$this->assertEquals($request['Attributes'], $result['Attributes']);
// test non-scoped attributes
$request['Attributes']['givenName'] = 'John Doe';
$result = $this->processFilter($config, $request);
$this->assertEquals($request['Attributes'], $result['Attributes']);
}
/**
* Test invalid scopes.
*/
public function testInvalidScopes()
{
// test scope not matching anything, empty attribute
$config = array();
$request = array(
'Source' => array(
'SingleSignOnService' => array(
array(
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'Location' => 'https://example.org/saml2/idp/SSOService.php',
),
),
'scope' => array(
'example.com',
'example.net',
),
),
'Attributes' => array(
'eduPersonPrincipalName' => array('jdoe@example.edu'),
),
);
$result = $this->processFilter($config, $request);
$this->assertEquals(array(), $result['Attributes']);
// test some scopes allowed and some others not
$request['Attributes']['eduPersonPrincipalName'][] = 'jdoe@example.com';
$result = $this->processFilter($config, $request);
$this->assertEquals(
array(
'eduPersonPrincipalName' => array(
'jdoe@example.com',
),
),
$result['Attributes']
);
// test attribute missing scope
$request['Attributes'] = array(
'eduPersonPrincipalName' => array('jdoe'),
);
$result = $this->processFilter($config, $request);
$this->assertEquals($request['Attributes'], $result['Attributes']);
}
}
simplesamlphp-1.15.3/tests/modules/saml/lib/Auth/Source/ 0000755 0000000 0000000 00000000000 13245225037 021635 5 ustar root root simplesamlphp-1.15.3/tests/modules/saml/lib/Auth/Source/Auth_Source_SP_Test.php 0000644 0000000 0000000 00000021371 13245225037 026174 0 ustar root root testResult = $testResult;
}
public function getTestResult()
{
return $this->testResult;
}
}
/**
* Wrap the SSP sspmod_saml_Auth_Source_SP class
* - Use introspection to make startSSO2Test available
* - Override sendSAML2AuthnRequest() to catch the AuthnRequest being sent
*/
class SP_Tester extends \sspmod_saml_Auth_Source_SP
{
public function __construct($info, $config)
{
parent::__construct($info, $config);
}
public function startSSO2Test(\SimpleSAML_Configuration $idpMetadata, array $state)
{
$reflector = new \ReflectionObject($this);
$method = $reflector->getMethod('startSSO2');
$method->setAccessible(true);
$method->invoke($this, $idpMetadata, $state);
}
// override the method that sends the request to avoid sending anything
public function sendSAML2AuthnRequest(array &$state, \SAML2\Binding $binding, \SAML2\AuthnRequest $ar)
{
// Exit test. Continuing would mean running into a assert(FALSE)
throw new ExitTestException(
array(
'state' => $state,
'binding' => $binding,
'ar' => $ar,
)
);
}
}
/**
* Set of test cases for sspmod_saml_Auth_Source_SP.
*/
class SP_Test extends \PHPUnit_Framework_TestCase
{
private $idpMetadata = null;
private $idpConfigArray;
private function getIdpMetadata()
{
if (!$this->idpMetadata) {
$this->idpMetadata = new \SimpleSAML_Configuration(
$this->idpConfigArray,
'Auth_Source_SP_Test::getIdpMetadata()'
);
}
return $this->idpMetadata;
}
protected function setUp()
{
$this->idpConfigArray = array(
'metadata-set' => 'saml20-idp-remote',
'entityid' => 'https://engine.surfconext.nl/authentication/idp/metadata',
'SingleSignOnService' => array(
array(
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'Location' => 'https://engine.surfconext.nl/authentication/idp/single-sign-on',
),
),
'keys' => array(
array(
'encryption' => false,
'signing' => true,
'type' => 'X509Certificate',
'X509Certificate' =>
'MIID3zCCAsegAwIBAgIJAMVC9xn1ZfsuMA0GCSqGSIb3DQEBCwUAMIGFMQswCQYDVQQGEwJOTDEQMA4GA1UECAwHVXRyZ'.
'WNodDEQMA4GA1UEBwwHVXRyZWNodDEVMBMGA1UECgwMU1VSRm5ldCBCLlYuMRMwEQYDVQQLDApTVVJGY29uZXh0MSYwJA'.
'YDVQQDDB1lbmdpbmUuc3VyZmNvbmV4dC5ubCAyMDE0MDUwNTAeFw0xNDA1MDUxNDIyMzVaFw0xOTA1MDUxNDIyMzVaMIG'.
'FMQswCQYDVQQGEwJOTDEQMA4GA1UECAwHVXRyZWNodDEQMA4GA1UEBwwHVXRyZWNodDEVMBMGA1UECgwMU1VSRm5ldCBC'.
'LlYuMRMwEQYDVQQLDApTVVJGY29uZXh0MSYwJAYDVQQDDB1lbmdpbmUuc3VyZmNvbmV4dC5ubCAyMDE0MDUwNTCCASIwD'.
'QYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKthMDbB0jKHefPzmRu9t2h7iLP4wAXr42bHpjzTEk6gttHFb4l/hFiz1Y'.
'BI88TjiH6hVjnozo/YHA2c51us+Y7g0XoS7653lbUN/EHzvDMuyis4Xi2Ijf1A/OUQfH1iFUWttIgtWK9+fatXoGUS6ti'.
'rQvrzVh6ZstEp1xbpo1SF6UoVl+fh7tM81qz+Crr/Kroan0UjpZOFTwxPoK6fdLgMAieKSCRmBGpbJHbQ2xxbdykBBrBb'.
'dfzIX4CDepfjE9h/40ldw5jRn3e392jrS6htk23N9BWWrpBT5QCk0kH3h/6F1Dm6TkyG9CDtt73/anuRkvXbeygI4wml9'.
'bL3rE8CAwEAAaNQME4wHQYDVR0OBBYEFD+Ac7akFxaMhBQAjVfvgGfY8hNKMB8GA1UdIwQYMBaAFD+Ac7akFxaMhBQAjV'.
'fvgGfY8hNKMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAC8L9D67CxIhGo5aGVu63WqRHBNOdo/FAGI7LUR'.
'DFeRmG5nRw/VXzJLGJksh4FSkx7aPrxNWF1uFiDZ80EuYQuIv7bDLblK31ZEbdg1R9LgiZCdYSr464I7yXQY9o6FiNtSK'.
'ZkQO8EsscJPPy/Zp4uHAnADWACkOUHiCbcKiUUFu66dX0Wr/v53Gekz487GgVRs8HEeT9MU1reBKRgdENR8PNg4rbQfLc'.
'3YQKLWK7yWnn/RenjDpuCiePj8N8/80tGgrNgK/6fzM3zI18sSywnXLswxqDb/J+jgVxnQ6MrsTf1urM8MnfcxG/82oHI'.
'wfMh/sXPCZpo+DTLkhQxctJ3M=',
),
),
);
$this->config = Configuration::loadFromArray(array(), '[ARRAY]', 'simplesaml');
}
/**
* Create a SAML AuthnRequest using sspmod_saml_Auth_Source_SP
*
* @param array $state The state array to use in the test. This is an array of the parameters described in section
* 2 of https://simplesamlphp.org/docs/development/saml:sp
*
* @return \SAML2\AuthnRequest The AuthnRequest generated.
*/
private function createAuthnRequest($state = array())
{
$info = array('AuthId' => 'default-sp');
$config = array();
$as = new SP_Tester($info, $config);
/** @var \SAML2\AuthnRequest $ar */
$ar = null;
try {
$as->startSSO2Test($this->getIdpMetadata(), $state);
$this->assertTrue(false, 'Expected ExitTestException');
} catch (ExitTestException $e) {
$r = $e->getTestResult();
$ar = $r['ar'];
}
return $ar;
}
/**
* Test generating an AuthnRequest
* @test
*/
public function testAuthnRequest()
{
/** @var \SAML2\AuthnRequest $ar */
$ar = $this->createAuthnRequest();
// Assert values in the generated AuthnRequest
/** @var $xml \DOMElement */
$xml = $ar->toSignedXML();
$q = \SAML2\Utils::xpQuery($xml, '/samlp:AuthnRequest/@Destination');
$this->assertEquals(
$this->idpConfigArray['SingleSignOnService'][0]['Location'],
$q[0]->value
);
$q = \SAML2\Utils::xpQuery($xml, '/samlp:AuthnRequest/saml:Issuer');
$this->assertEquals(
'http://localhost/simplesaml/module.php/saml/sp/metadata.php/default-sp',
$q[0]->textContent
);
}
/**
* Test setting a Subject
* @test *
*/
public function testNameID()
{
$state = array(
'saml:NameID' => array('Value' => 'user@example.org', 'Format' => \SAML2\Constants::NAMEID_UNSPECIFIED)
);
/** @var \SAML2\AuthnRequest $ar */
$ar = $this->createAuthnRequest($state);
$nameID = $ar->getNameId();
$this->assertEquals($state['saml:NameID']['Value'], $nameID->value);
$this->assertEquals($state['saml:NameID']['Format'], $nameID->Format);
/** @var $xml \DOMElement */
$xml = $ar->toSignedXML();
$q = \SAML2\Utils::xpQuery($xml, '/samlp:AuthnRequest/saml:Subject/saml:NameID/@Format');
$this->assertEquals(
$state['saml:NameID']['Format'],
$q[0]->value
);
$q = \SAML2\Utils::xpQuery($xml, '/samlp:AuthnRequest/saml:Subject/saml:NameID');
$this->assertEquals(
$state['saml:NameID']['Value'],
$q[0]->textContent
);
}
/**
* Test setting an AuthnConextClassRef
* @test *
*/
public function testAuthnContextClassRef()
{
$state = array(
'saml:AuthnContextClassRef' => 'http://example.com/myAuthnContextClassRef'
);
/** @var \SAML2\AuthnRequest $ar */
$ar = $this->createAuthnRequest($state);
$a = $ar->getRequestedAuthnContext();
$this->assertEquals(
$state['saml:AuthnContextClassRef'],
$a['AuthnContextClassRef'][0]
);
/** @var $xml \DOMElement */
$xml = $ar->toSignedXML();
$q = \SAML2\Utils::xpQuery($xml, '/samlp:AuthnRequest/samlp:RequestedAuthnContext/saml:AuthnContextClassRef');
$this->assertEquals(
$state['saml:AuthnContextClassRef'],
$q[0]->textContent
);
}
/**
* Test setting ForcedAuthn
* @test *
*/
public function testForcedAuthn()
{
$state = array(
'ForceAuthn' => true
);
/** @var \SAML2\AuthnRequest $ar */
$ar = $this->createAuthnRequest($state);
$this->assertEquals(
$state['ForceAuthn'],
$ar->getForceAuthn()
);
/** @var $xml \DOMElement */
$xml = $ar->toSignedXML();
$q = \SAML2\Utils::xpQuery($xml, '/samlp:AuthnRequest/@ForceAuthn');
$this->assertEquals(
$state['ForceAuthn'] ? 'true' : 'false',
$q[0]->value
);
}
}
simplesamlphp-1.15.3/tests/modules/ldap/ 0000755 0000000 0000000 00000000000 13245225037 016712 5 ustar root root simplesamlphp-1.15.3/tests/modules/ldap/lib/ 0000755 0000000 0000000 00000000000 13245225037 017460 5 ustar root root simplesamlphp-1.15.3/tests/modules/ldap/lib/Auth/ 0000755 0000000 0000000 00000000000 13245225037 020361 5 ustar root root simplesamlphp-1.15.3/tests/modules/ldap/lib/Auth/Process/ 0000755 0000000 0000000 00000000000 13245225037 021777 5 ustar root root simplesamlphp-1.15.3/tests/modules/ldap/lib/Auth/Process/BaseFilterTest.php 0000644 0000000 0000000 00000001470 13245225037 025372 0 ustar root root getMockBuilder('sspmod_ldap_Auth_Process_BaseFilter')
->disableOriginalConstructor()
->getMockForAbstractClass();
$class = new \ReflectionClass($stub);
$method = $class->getMethod('var_export');
$method->setAccessible(true);
$this->assertEquals(
"array ( 'ldap.hostname' => 'ldap://172.17.101.32', 'ldap.port' => 389, 'ldap.password' => '********', )",
$method->invokeArgs($stub, array(array(
'ldap.hostname' => 'ldap://172.17.101.32',
'ldap.port' => 389,
'ldap.password' => 'password',
)))
);
}
}
simplesamlphp-1.15.3/tests/BuiltInServer.php 0000644 0000000 0000000 00000012770 13245225037 017577 0 ustar root root
* @package SimpleSAMLphp
*/
namespace SimpleSAML\Test;
class BuiltInServer
{
/**
* The PID of the running server.
*
* @var int
*/
protected $pid = 0;
/**
* The address (host:port) where the server is listening for connections after being started.
*
* @var string
*/
protected $address;
/**
* The name of a "router" file to run for every request performed to this server.
*
* @var string
*/
protected $router = '';
/**
* The document root of the server.
*
* @var string
*/
protected $docroot;
/**
* BuiltInServer constructor.
*
* @param string|null $router The name of a "router" file to run first for every request performed to this server.
* @param string|null $docroot The document root to use when starting the server.
*
* @see http://php.net/manual/en/features.commandline.webserver.php
*/
public function __construct($router = null, $docroot = null)
{
if (!is_null($router)) {
$this->setRouter($router);
}
if (!is_null($docroot)) {
$this->docroot = $docroot;
} else {
$this->docroot = dirname(dirname(__FILE__)).'/www/';
}
}
/**
* Start the built-in server in a random port.
*
* This method will wait up to 5 seconds for the server to start. When it returns an address, it is guaranteed that
* the server has started and is listening for connections. If it returns false on the other hand, there will be no
* guarantee that the server started properly.
*
* @return string The address where the server is listening for connections, or false if the server failed to start
* for some reason.
*
* @todo This method should be resilient to clashes in the randomly-picked port number.
*/
public function start()
{
$port = mt_rand(1025, 65535);
$this->address = 'localhost:'.$port;
$command = sprintf(
'php -S %s -t %s %s >> /dev/null 2>&1 & echo $!',
$this->address,
$this->docroot,
$this->router
);
// execute the command and store the process ID
$output = array();
exec($command, $output);
$this->pid = (int) $output[0];
// wait until it's listening for connections to avoid race conditions
$start = microtime(true);
while (($sock = @fsockopen('localhost', $port, $errno, $errstr, 10)) === false) {
// set a 5 secs timeout waiting for the server to start
if (microtime(true) > $start + 5) {
$this->pid = false; // signal failure
$this->address = false;
break;
}
}
if ($sock !== false) {
fclose($sock);
}
return $this->address;
}
/**
* Stop the built-in server.
*/
public function stop()
{
if ($this->pid === 0) {
return;
}
exec('kill '.$this->pid);
$this->pid = 0;
}
/**
* Get the PID of the running server.
*
* @return int The PID of the server, or 0 if the server was not started.
*/
public function getPid()
{
return $this->pid;
}
/**
* Get the name of the "router" file.
*
* @return string The name of the "router" file.
*/
public function getRouter()
{
return $this->router;
}
/**
* Set the "router" file.
*
* @param string $router The name of a "router" file to use when starting the server.
*/
public function setRouter($router)
{
$file = dirname(dirname(__FILE__)).'/tests/routers/'.$router.'.php';
if (!file_exists($file)) {
throw new \InvalidArgumentException('Unknown router "'.$router.'".');
}
$this->router = $file;
}
/**
* This function performs an HTTP GET request to the built-in server.
*
* @param string $query The query to perform.
* @param array $parameters An array (can be empty) with parameters for the requested URI.
* @param array $curlopts An array (can be empty) with options for cURL.
*
* @return array|string The response obtained from the built-in server.
*/
public function get($query, $parameters, $curlopts = array())
{
$ch = curl_init();
$url = 'http://'.$this->address.$query;
$url .= (!empty($parameters)) ? '?'.http_build_query($parameters) : '';
curl_setopt_array($ch, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HEADER => 1,
));
curl_setopt_array($ch, $curlopts);
$resp = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
list($header, $body) = explode("\r\n\r\n", $resp, 2);
$raw_headers = explode("\r\n", $header);
array_shift($raw_headers);
$headers = array();
foreach ($raw_headers as $header) {
list($name, $value) = explode(':', $header, 2);
$headers[trim($name)] = trim($value);
}
curl_close($ch);
return array(
'code' => $code,
'headers' => $headers,
'body' => $body,
);
}
}
simplesamlphp-1.15.3/tests/www/ 0000755 0000000 0000000 00000000000 13245225037 015146 5 ustar root root simplesamlphp-1.15.3/tests/www/IndexTest.php 0000644 0000000 0000000 00000006770 13245225037 017600 0 ustar root root
* @package SimpleSAMLphp
*/
namespace SimpleSAML\Test\Web;
include(dirname(__FILE__).'/../BuiltInServer.php');
use \SimpleSAML\Test\BuiltInServer;
class IndexTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \SimpleSAML\Test\BuiltInServer
*/
protected $server;
/**
* @var string
*/
protected $server_addr;
/**
* @var int
*/
protected $server_pid;
/**
* @var string
*/
protected $shared_file;
/**
* The setup method that is run before any tests in this class.
*/
protected function setup()
{
$this->server = new BuiltInServer('configLoader');
$this->server_addr = $this->server->start();
$this->server_pid = $this->server->getPid();
$this->shared_file = sys_get_temp_dir().'/'.$this->server_pid.'.lock';
@unlink($this->shared_file); // remove it if it exists
}
protected function updateConfig($config)
{
@unlink($this->shared_file);
$config = "shared_file, $config);
}
/**
* A simple test to make sure the index.php file redirects appropriately to the right URL.
*/
public function testRedirection()
{
if (defined('HHVM_VERSION')) {
// can't test this in HHVM for the moment
$this->markTestSkipped('The web-based tests cannot be run in HHVM for the moment.');
}
if (version_compare(phpversion(), '5.4') === -1) {
// no built-in server prior to 5.4
$this->markTestSkipped('The web-based tests cannot be run in PHP versions older than 5.4.');
}
// test most basic redirection
$this->updateConfig(array(
'baseurlpath' => 'http://example.org/simplesaml/'
));
$resp = $this->server->get('/index.php', array(), array(
CURLOPT_FOLLOWLOCATION => 0,
));
$this->assertEquals('302', $resp['code']);
$this->assertEquals(
'http://example.org/simplesaml/module.php/core/frontpage_welcome.php',
$resp['headers']['Location']
);
// test non-default path and https
$this->updateConfig(array(
'baseurlpath' => 'https://example.org/'
));
$resp = $this->server->get('/index.php', array(), array(
CURLOPT_FOLLOWLOCATION => 0,
));
$this->assertEquals('302', $resp['code']);
$this->assertEquals(
'https://example.org/module.php/core/frontpage_welcome.php',
$resp['headers']['Location']
);
// test URL guessing
$this->updateConfig(array(
'baseurlpath' => '/simplesaml/'
));
$resp = $this->server->get('/index.php', array(), array(
CURLOPT_FOLLOWLOCATION => 0,
));
$this->assertEquals('302', $resp['code']);
$this->assertEquals(
'http://'.$this->server_addr.'/simplesaml/module.php/core/frontpage_welcome.php',
$resp['headers']['Location']
);
}
/**
* The tear down method that is executed after all tests in this class.
*/
protected function tearDown()
{
unlink($this->shared_file);
$this->server->stop();
}
}
simplesamlphp-1.15.3/tests/bootstrap.php 0000644 0000000 0000000 00000000344 13245225037 017051 0 ustar root root
* @package simplesamlphp/simplesamlphp
*/
class StoreTest extends \PHPUnit_Framework_TestCase
{
/**
* @covers \SimpleSAML\Store::getInstance
* @test
*/
public function defaultStore()
{
Configuration::loadFromArray(array(
), '[ARRAY]', 'simplesaml');
$store = Store::getInstance();
$this->assertEquals(false, $store);
}
/**
* @covers \SimpleSAML\Store::getInstance
* @test
*/
public function phpSessionStore()
{
Configuration::loadFromArray(array(
), '[ARRAY]', 'simplesaml');
$store = Store::getInstance();
$this->assertEquals(false, $store);
}
/**
* @covers \SimpleSAML\Store::getInstance
* @test
*/
public function memcacheStore()
{
Configuration::loadFromArray(array(
'store.type' => 'memcache',
), '[ARRAY]', 'simplesaml');
$store = Store::getInstance();
$this->assertInstanceOf('\SimpleSAML\Store\Memcache', $store);
}
/**
* @covers \SimpleSAML\Store::getInstance
* @test
*/
public function sqlStore()
{
Configuration::loadFromArray(array(
'store.type' => 'sql',
'store.sql.dsn' => 'sqlite::memory:',
'store.sql.prefix' => 'phpunit_',
), '[ARRAY]', 'simplesaml');
$store = Store::getInstance();
$this->assertInstanceOf('SimpleSAML\Store\SQL', $store);
}
/**
* @covers \SimpleSAML\Store::getInstance
* @test
*/
public function pathStore()
{
Configuration::loadFromArray(array(
'store.type' => '\SimpleSAML\Store\SQL',
'store.sql.dsn' => 'sqlite::memory:',
'store.sql.prefix' => 'phpunit_',
), '[ARRAY]', 'simplesaml');
$store = Store::getInstance();
$this->assertInstanceOf('SimpleSAML\Store\SQL', $store);
}
/**
* @covers \SimpleSAML\Store::getInstance
* @expectedException \SimpleSAML\Error\CriticalConfigurationError
* @test
*/
public function notFoundStoreException()
{
Configuration::loadFromArray(array(
'store.type' => '\Test\SimpleSAML\Store\Dummy',
'store.sql.dsn' => 'sqlite::memory:',
'store.sql.prefix' => 'phpunit_',
), '[ARRAY]', 'simplesaml');
Store::getInstance();
}
protected function tearDown()
{
$config = Configuration::getInstance();
$store = Store::getInstance();
$this->clearInstance($config, '\SimpleSAML_Configuration');
$this->clearInstance($store, '\SimpleSAML\Store');
}
protected function clearInstance($service, $className)
{
$reflectedClass = new \ReflectionClass($className);
$reflectedInstance = $reflectedClass->getProperty('instance');
$reflectedInstance->setAccessible(true);
$reflectedInstance->setValue($service, null);
$reflectedInstance->setAccessible(false);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/ConfigurationTest.php 0000644 0000000 0000000 00000104774 13245225037 023173 0 ustar root root assertTrue(is_string($c->getVersion()));
}
/**
* Test that the default instance fails to load even if we previously loaded another instance.
* @expectedException \SimpleSAML\Error\CriticalConfigurationError
*/
public function testLoadDefaultInstance()
{
SimpleSAML_Configuration::loadFromArray(array('key' => 'value'), '', 'dummy');
SimpleSAML_Configuration::getInstance();
}
/**
* Test that after a \SimpleSAML\Error\CriticalConfigurationError exception, a basic, self-survival configuration
* is loaded.
*/
public function testCriticalConfigurationError()
{
try {
SimpleSAML_Configuration::getInstance();
$this->fail('Exception expected');
} catch (\SimpleSAML\Error\CriticalConfigurationError $var) {
// This exception is expected.
}
/*
* After the above failure an emergency configuration is create to allow core SSP components to function and
* possibly log/display the error.
*/
$c = SimpleSAML_Configuration::getInstance();
$this->assertNotEmpty($c->toArray());
}
/**
* Test SimpleSAML_Configuration::getValue()
*/
public function testGetValue() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'exists_true' => true,
'exists_null' => null,
));
$this->assertEquals($c->getValue('missing'), null);
$this->assertEquals($c->getValue('missing', true), true);
$this->assertEquals($c->getValue('missing', true), true);
$this->assertEquals($c->getValue('exists_true'), true);
$this->assertEquals($c->getValue('exists_null'), null);
$this->assertEquals($c->getValue('exists_null', false), null);
}
/**
* Test SimpleSAML_Configuration::getValue(), REQUIRED_OPTION flag.
* @expectedException Exception
*/
public function testGetValueRequired() {
$c = SimpleSAML_Configuration::loadFromArray(array());
$c->getValue('missing', SimpleSAML_Configuration::REQUIRED_OPTION);
}
/**
* Test SimpleSAML_Configuration::hasValue()
*/
public function testHasValue() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'exists_true' => true,
'exists_null' => null,
));
$this->assertEquals($c->hasValue('missing'), false);
$this->assertEquals($c->hasValue('exists_true'), true);
$this->assertEquals($c->hasValue('exists_null'), true);
}
/**
* Test SimpleSAML_Configuration::hasValue()
*/
public function testHasValueOneOf() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'exists_true' => true,
'exists_null' => null,
));
$this->assertEquals($c->hasValueOneOf(array()), false);
$this->assertEquals($c->hasValueOneOf(array('missing')), false);
$this->assertEquals($c->hasValueOneOf(array('exists_true')), true);
$this->assertEquals($c->hasValueOneOf(array('exists_null')), true);
$this->assertEquals($c->hasValueOneOf(array('missing1', 'missing2')), false);
$this->assertEquals($c->hasValueOneOf(array('exists_true', 'missing')), true);
$this->assertEquals($c->hasValueOneOf(array('missing', 'exists_true')), true);
}
/**
* Test SimpleSAML_Configuration::getBaseURL()
*/
public function testGetBaseURL() {
// Need to set a default configuration because the SSP Logger attempts to use it.
SimpleSAML_Configuration::loadFromArray(array(), '[ARRAY]', 'simplesaml');
$c = SimpleSAML_Configuration::loadFromArray(array());
$this->assertEquals($c->getBaseURL(), 'simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'simplesaml/'));
$this->assertEquals($c->getBaseURL(), 'simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => '/simplesaml/'));
$this->assertEquals($c->getBaseURL(), 'simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'path/to/simplesaml/'));
$this->assertEquals($c->getBaseURL(), 'path/to/simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => '/path/to/simplesaml/'));
$this->assertEquals($c->getBaseURL(), 'path/to/simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'https://example.org/ssp/'));
$this->assertEquals($c->getBaseURL(), 'ssp/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'https://example.org/'));
$this->assertEquals($c->getBaseURL(), '');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'http://example.org/ssp/'));
$this->assertEquals($c->getBaseURL(), 'ssp/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => ''));
$this->assertEquals($c->getBaseURL(), '');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => '/'));
$this->assertEquals($c->getBaseURL(), '');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'simplesaml'));
$this->assertEquals($c->getBaseURL(), 'simplesaml/');
}
/**
* Test SimpleSAML_Configuration::getBasePath()
*/
public function testGetBasePath() {
$c = SimpleSAML_Configuration::loadFromArray(array());
$this->assertEquals($c->getBasePath(), '/simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'simplesaml/'));
$this->assertEquals($c->getBasePath(), '/simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => '/simplesaml/'));
$this->assertEquals($c->getBasePath(), '/simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'simplesaml'));
$this->assertEquals($c->getBasePath(), '/simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => '/simplesaml'));
$this->assertEquals($c->getBasePath(), '/simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'path/to/simplesaml/'));
$this->assertEquals($c->getBasePath(), '/path/to/simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => '/path/to/simplesaml/'));
$this->assertEquals($c->getBasePath(), '/path/to/simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => '/path/to/simplesaml'));
$this->assertEquals($c->getBasePath(), '/path/to/simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'https://example.org/ssp/'));
$this->assertEquals($c->getBasePath(), '/ssp/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'https://example.org/'));
$this->assertEquals($c->getBasePath(), '/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'http://example.org/ssp/'));
$this->assertEquals($c->getBasePath(), '/ssp/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'http://example.org/ssp/simplesaml'));
$this->assertEquals($c->getBasePath(), '/ssp/simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'http://example.org/ssp/simplesaml/'));
$this->assertEquals($c->getBasePath(), '/ssp/simplesaml/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => ''));
$this->assertEquals($c->getBasePath(), '/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => '/'));
$this->assertEquals($c->getBasePath(), '/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'https://example.org:8443'));
$this->assertEquals($c->getBasePath(), '/');
$c = SimpleSAML_Configuration::loadFromArray(array('baseurlpath' => 'https://example.org:8443/'));
$this->assertEquals($c->getBasePath(), '/');
}
/**
* Test SimpleSAML_Configuration::resolvePath()
*/
public function testResolvePath() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'basedir' => '/basedir/',
));
$this->assertEquals($c->resolvePath(null), null);
$this->assertEquals($c->resolvePath('/otherdir'), '/otherdir');
$this->assertEquals($c->resolvePath('relativedir'), '/basedir/relativedir');
$this->assertEquals($c->resolvePath('slash/'), '/basedir/slash');
$this->assertEquals($c->resolvePath('slash//'), '/basedir/slash');
}
/**
* Test SimpleSAML_Configuration::getPathValue()
*/
public function testGetPathValue() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'basedir' => '/basedir/',
'path_opt' => 'path',
'slashes_opt' => 'slashes//',
));
$this->assertEquals($c->getPathValue('missing'), null);
$this->assertEquals($c->getPathValue('path_opt'), '/basedir/path/');
$this->assertEquals($c->getPathValue('slashes_opt'), '/basedir/slashes/');
}
/**
* Test SimpleSAML_Configuration::getBaseDir()
*/
public function testGetBaseDir() {
$c = SimpleSAML_Configuration::loadFromArray(array());
$this->assertEquals($c->getBaseDir(), dirname(dirname(dirname(dirname(__FILE__)))) . '/');
$c = SimpleSAML_Configuration::loadFromArray(array(
'basedir' => '/basedir',
));
$this->assertEquals($c->getBaseDir(), '/basedir/');
$c = SimpleSAML_Configuration::loadFromArray(array(
'basedir' => '/basedir/',
));
$this->assertEquals($c->getBaseDir(), '/basedir/');
}
/**
* Test SimpleSAML_Configuration::getBoolean()
*/
public function testGetBoolean() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'true_opt' => true,
'false_opt' => false,
));
$this->assertEquals($c->getBoolean('missing_opt', '--missing--'), '--missing--');
$this->assertEquals($c->getBoolean('true_opt', '--missing--'), true);
$this->assertEquals($c->getBoolean('false_opt', '--missing--'), false);
}
/**
* Test SimpleSAML_Configuration::getBoolean() missing option
* @expectedException Exception
*/
public function testGetBooleanMissing() {
$c = SimpleSAML_Configuration::loadFromArray(array());
$c->getBoolean('missing_opt');
}
/**
* Test SimpleSAML_Configuration::getBoolean() wrong option
* @expectedException Exception
*/
public function testGetBooleanWrong() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'wrong' => 'true',
));
$c->getBoolean('wrong');
}
/**
* Test SimpleSAML_Configuration::getString()
*/
public function testGetString() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'str_opt' => 'Hello World!',
));
$this->assertEquals($c->getString('missing_opt', '--missing--'), '--missing--');
$this->assertEquals($c->getString('str_opt', '--missing--'), 'Hello World!');
}
/**
* Test SimpleSAML_Configuration::getString() missing option
* @expectedException Exception
*/
public function testGetStringMissing() {
$c = SimpleSAML_Configuration::loadFromArray(array());
$c->getString('missing_opt');
}
/**
* Test SimpleSAML_Configuration::getString() wrong option
* @expectedException Exception
*/
public function testGetStringWrong() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'wrong' => false,
));
$c->getString('wrong');
}
/**
* Test SimpleSAML_Configuration::getInteger()
*/
public function testGetInteger() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'int_opt' => 42,
));
$this->assertEquals($c->getInteger('missing_opt', '--missing--'), '--missing--');
$this->assertEquals($c->getInteger('int_opt', '--missing--'), 42);
}
/**
* Test SimpleSAML_Configuration::getInteger() missing option
* @expectedException Exception
*/
public function testGetIntegerMissing() {
$c = SimpleSAML_Configuration::loadFromArray(array());
$c->getInteger('missing_opt');
}
/**
* Test SimpleSAML_Configuration::getInteger() wrong option
* @expectedException Exception
*/
public function testGetIntegerWrong() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'wrong' => '42',
));
$c->getInteger('wrong');
}
/**
* Test SimpleSAML_Configuration::getIntegerRange()
*/
public function testGetIntegerRange() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'int_opt' => 42,
));
$this->assertEquals($c->getIntegerRange('missing_opt', 0, 100, '--missing--'), '--missing--');
$this->assertEquals($c->getIntegerRange('int_opt', 0, 100), 42);
}
/**
* Test SimpleSAML_Configuration::getIntegerRange() below limit
* @expectedException Exception
*/
public function testGetIntegerRangeBelow() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'int_opt' => 9,
));
$this->assertEquals($c->getIntegerRange('int_opt', 10, 100), 42);
}
/**
* Test SimpleSAML_Configuration::getIntegerRange() above limit
* @expectedException Exception
*/
public function testGetIntegerRangeAbove() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'int_opt' => 101,
));
$this->assertEquals($c->getIntegerRange('int_opt', 10, 100), 42);
}
/**
* Test SimpleSAML_Configuration::getValueValidate()
*/
public function testGetValueValidate() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'opt' => 'b',
));
$this->assertEquals($c->getValueValidate('missing_opt', array('a', 'b', 'c'), '--missing--'), '--missing--');
$this->assertEquals($c->getValueValidate('opt', array('a', 'b', 'c')), 'b');
}
/**
* Test SimpleSAML_Configuration::getValueValidate() wrong option
* @expectedException Exception
*/
public function testGetValueValidateWrong() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'opt' => 'd',
));
$c->getValueValidate('opt', array('a', 'b', 'c'));
}
/**
* Test SimpleSAML_Configuration::getArray()
*/
public function testGetArray() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'opt' => array('a', 'b', 'c'),
));
$this->assertEquals($c->getArray('missing_opt', '--missing--'), '--missing--');
$this->assertEquals($c->getArray('opt'), array('a', 'b', 'c'));
}
/**
* Test SimpleSAML_Configuration::getArray() wrong option
* @expectedException Exception
*/
public function testGetArrayWrong() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'opt' => 'not_an_array',
));
$c->getArray('opt');
}
/**
* Test SimpleSAML_Configuration::getArrayize()
*/
public function testGetArrayize() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'opt' => array('a', 'b', 'c'),
'opt_int' => 42,
'opt_str' => 'string',
));
$this->assertEquals($c->getArrayize('missing_opt', '--missing--'), '--missing--');
$this->assertEquals($c->getArrayize('opt'), array('a', 'b', 'c'));
$this->assertEquals($c->getArrayize('opt_int'), array(42));
$this->assertEquals($c->getArrayize('opt_str'), array('string'));
}
/**
* Test SimpleSAML_Configuration::getArrayizeString()
*/
public function testGetArrayizeString() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'opt' => array('a', 'b', 'c'),
'opt_str' => 'string',
));
$this->assertEquals($c->getArrayizeString('missing_opt', '--missing--'), '--missing--');
$this->assertEquals($c->getArrayizeString('opt'), array('a', 'b', 'c'));
$this->assertEquals($c->getArrayizeString('opt_str'), array('string'));
}
/**
* Test SimpleSAML_Configuration::getArrayizeString() option with an array that contains something that isn't a string.
* @expectedException Exception
*/
public function testGetArrayizeStringWrongValue() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'opt' => array('a', 'b', 42),
));
$c->getArrayizeString('opt');
}
/**
* Test SimpleSAML_Configuration::getConfigItem()
*/
public function testGetConfigItem() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'opt' => array('a' => 42),
));
$this->assertEquals($c->getConfigItem('missing_opt', '--missing--'), '--missing--');
$opt = $c->getConfigItem('opt');
$this->assertInstanceOf('SimpleSAML_Configuration', $opt);
$this->assertEquals($opt->getValue('a'), 42);
}
/**
* Test SimpleSAML_Configuration::getConfigItem() wrong option
* @expectedException Exception
*/
public function testGetConfigItemWrong() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'opt' => 'not_an_array',
));
$c->getConfigItem('opt');
}
/**
* Test SimpleSAML_Configuration::getConfigList()
*/
public function testGetConfigList() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'opts' => array(
'a' => array('opt1' => 'value1'),
'b' => array('opt2' => 'value2'),
),
));
$this->assertEquals($c->getConfigList('missing_opt', '--missing--'), '--missing--');
$opts = $c->getConfigList('opts');
$this->assertInternalType('array', $opts);
$this->assertEquals(array_keys($opts), array('a', 'b'));
$this->assertInstanceOf('SimpleSAML_Configuration', $opts['a']);
$this->assertEquals($opts['a']->getValue('opt1'), 'value1');
$this->assertInstanceOf('SimpleSAML_Configuration', $opts['b']);
$this->assertEquals($opts['b']->getValue('opt2'), 'value2');
}
/**
* Test SimpleSAML_Configuration::getConfigList() wrong option
* @expectedException Exception
*/
public function testGetConfigListWrong() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'opt' => 'not_an_array',
));
$c->getConfigList('opt');
}
/**
* Test SimpleSAML_Configuration::getConfigList() with an array of wrong options.
* @expectedException Exception
*/
public function testGetConfigListWrongArrayValues()
{
$c = SimpleSAML_Configuration::loadFromArray(array(
'opts' => array(
'a',
'b',
),
));
$c->getConfigList('opts');
}
/**
* Test SimpleSAML_Configuration::getOptions()
*/
public function testGetOptions() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'a' => true,
'b' => null,
));
$this->assertEquals($c->getOptions(), array('a', 'b'));
}
/**
* Test SimpleSAML_Configuration::toArray()
*/
public function testToArray() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'a' => true,
'b' => null,
));
$this->assertEquals($c->toArray(), array('a' => true, 'b' => null));
}
/**
* Test SimpleSAML_Configuration::getDefaultEndpoint().
*
* Iterate over all different valid definitions of endpoints and check if the expected output is produced.
*/
public function testGetDefaultEndpoint()
{
/*
* First we run the full set of tests covering all possible configurations for indexed endpoint types,
* basically AssertionConsumerService and ArtifactResolutionService. Since both are the same, we just run the
* tests for AssertionConsumerService.
*/
$acs_eps = array(
// just a string with the location
'https://example.com/endpoint.php',
// an array of strings with location of different endpoints
array(
'https://www1.example.com/endpoint.php',
'https://www2.example.com/endpoint.php',
),
// define location and binding
array(
array(
'Location' => 'https://example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_POST,
),
),
// define the ResponseLocation too
array(
array(
'Location' => 'https://example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_POST,
'ResponseLocation' => 'https://example.com/endpoint.php',
),
),
// make sure indexes are NOT taken into account (they just identify endpoints)
array(
array(
'index' => 1,
'Location' => 'https://www1.example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_REDIRECT,
),
array(
'index' => 2,
'Location' => 'https://www2.example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_POST,
),
),
// make sure isDefault has priority over indexes
array(
array(
'index' => 1,
'Location' => 'https://www2.example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_POST,
),
array(
'index' => 2,
'isDefault' => true,
'Location' => 'https://www1.example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_REDIRECT,
),
),
// make sure endpoints with invalid bindings are ignored and those marked as NOT default are still used
array(
array(
'index' => 1,
'Location' => 'https://www1.example.com/endpoint.php',
'Binding' => 'invalid_binding',
),
array(
'index' => 2,
'isDefault' => false,
'Location' => 'https://www2.example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_POST,
),
),
);
$acs_expected_eps = array(
// output should be completed with the default binding (HTTP-POST for ACS)
array(
'Location' => 'https://example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_POST,
),
// we should just get the first endpoint with the default binding
array(
'Location' => 'https://www1.example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_POST,
),
// if we specify the binding, we should get it back
array(
'Location' => 'https://example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_POST
),
// if we specify ResponseLocation, we should get it back too
array(
'Location' => 'https://example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_POST,
'ResponseLocation' => 'https://example.com/endpoint.php',
),
// indexes must NOT be taken into account, order is the only thing that matters here
array(
'Location' => 'https://www1.example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_REDIRECT,
'index' => 1,
),
// isDefault must have higher priority than indexes
array(
'Location' => 'https://www1.example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_REDIRECT,
'isDefault' => true,
'index' => 2,
),
// the first valid enpoint should be used even if it's marked as NOT default
array(
'index' => 2,
'isDefault' => false,
'Location' => 'https://www2.example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_POST,
)
);
$a = array(
'metadata-set' => 'saml20-sp-remote',
'ArtifactResolutionService' => 'https://example.com/ars',
'SingleSignOnService' => 'https://example.com/sso',
'SingleLogoutService' => array(
'Location' => 'https://example.com/slo',
'Binding' => 'valid_binding', // test unknown bindings if we don't specify a list of valid ones
),
);
$valid_bindings = array(
\SAML2\Constants::BINDING_HTTP_POST,
\SAML2\Constants::BINDING_HTTP_REDIRECT,
\SAML2\Constants::BINDING_HOK_SSO,
\SAML2\Constants::BINDING_HTTP_ARTIFACT.
\SAML2\Constants::BINDING_SOAP,
);
// run all general tests with AssertionConsumerService endpoint type
foreach ($acs_eps as $i => $ep) {
$a['AssertionConsumerService'] = $ep;
$c = SimpleSAML_Configuration::loadFromArray($a);
$this->assertEquals($acs_expected_eps[$i], $c->getDefaultEndpoint(
'AssertionConsumerService',
$valid_bindings
));
}
// now make sure SingleSignOnService, SingleLogoutService and ArtifactResolutionService works fine
$a['metadata-set'] = 'shib13-idp-remote';
$c = SimpleSAML_Configuration::loadFromArray($a);
$this->assertEquals(
array(
'Location' => 'https://example.com/sso',
'Binding' => 'urn:mace:shibboleth:1.0:profiles:AuthnRequest',
),
$c->getDefaultEndpoint('SingleSignOnService')
);
$a['metadata-set'] = 'saml20-idp-remote';
$c = SimpleSAML_Configuration::loadFromArray($a);
$this->assertEquals(
array(
'Location' => 'https://example.com/ars',
'Binding' => \SAML2\Constants::BINDING_SOAP,
),
$c->getDefaultEndpoint('ArtifactResolutionService')
);
$this->assertEquals(
array(
'Location' => 'https://example.com/slo',
'Binding' => \SAML2\Constants::BINDING_HTTP_REDIRECT,
),
$c->getDefaultEndpoint('SingleLogoutService')
);
// test for old shib1.3 AssertionConsumerService
$a['metadata-set'] = 'shib13-sp-remote';
$a['AssertionConsumerService'] = 'https://example.com/endpoint.php';
$c = SimpleSAML_Configuration::loadFromArray($a);
$this->assertEquals(
array(
'Location' => 'https://example.com/endpoint.php',
'Binding' => 'urn:oasis:names:tc:SAML:1.0:profiles:browser-post',
),
$c->getDefaultEndpoint('AssertionConsumerService')
);
// test for no valid endpoints specified
$a['SingleLogoutService'] = array(
array(
'Location' => 'https://example.com/endpoint.php',
'Binding' => 'invalid_binding',
'isDefault' => true,
),
);
$c = SimpleSAML_Configuration::loadFromArray($a);
try {
$c->getDefaultEndpoint('SingleLogoutService', $valid_bindings);
$this->fail('Failed to detect invalid endpoint binding.');
} catch (Exception $e) {
$this->assertEquals(
'[ARRAY][\'SingleLogoutService\']:Could not find a supported SingleLogoutService '.'endpoint.',
$e->getMessage()
);
}
$a['metadata-set'] = 'foo';
$c = SimpleSAML_Configuration::loadFromArray($a);
try {
$c->getDefaultEndpoint('SingleSignOnService');
$this->fail('No valid metadata set specified.');
} catch (Exception $e) {
$this->assertStringStartsWith('Missing default binding for', $e->getMessage());
}
}
/**
* Test SimpleSAML_Configuration::getEndpoints().
*/
public function testGetEndpoints()
{
// test response location for old-style configurations
$c = SimpleSAML_Configuration::loadFromArray(array(
'metadata-set' => 'saml20-idp-remote',
'SingleSignOnService' => 'https://example.com/endpoint.php',
'SingleSignOnServiceResponse' => 'https://example.com/response.php',
));
$e = array(
array(
'Location' => 'https://example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_REDIRECT,
'ResponseLocation' => 'https://example.com/response.php',
)
);
$this->assertEquals($e, $c->getEndpoints('SingleSignOnService'));
// test for input failures
// define a basic configuration array
$a = array(
'metadata-set' => 'saml20-idp-remote',
'SingleSignOnService' => null,
);
// define a set of tests
$tests = array(
// invalid endpoint definition
10,
// invalid definition of endpoint inside the endpoints array
array(
1234
),
// missing location
array(
array(
'foo' => 'bar',
),
),
// invalid location
array(
array(
'Location' => 1234,
)
),
// missing binding
array(
array(
'Location' => 'https://example.com/endpoint.php',
),
),
// invalid binding
array(
array(
'Location' => 'https://example.com/endpoint.php',
'Binding' => 1234,
),
),
// invalid response location
array(
array(
'Location' => 'https://example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_REDIRECT,
'ResponseLocation' => 1234,
),
),
// invalid index
array(
array(
'Location' => 'https://example.com/endpoint.php',
'Binding' => \SAML2\Constants::BINDING_HTTP_REDIRECT,
'index' => 'string',
),
),
);
// define a set of exception messages to expect
$msgs = array(
'Expected array or string.',
'Expected a string or an array.',
'Missing Location.',
'Location must be a string.',
'Missing Binding.',
'Binding must be a string.',
'ResponseLocation must be a string.',
'index must be an integer.',
);
// now run all the tests expecting the correct exception message
foreach ($tests as $i => $test) {
$a['SingleSignOnService'] = $test;
$c = SimpleSAML_Configuration::loadFromArray($a);
try {
$c->getEndpoints('SingleSignOnService');
} catch (Exception $e) {
$this->assertStringEndsWith($msgs[$i], $e->getMessage());
}
}
}
/**
* Test SimpleSAML_Configuration::getLocalizedString()
*/
public function testGetLocalizedString() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'str_opt' => 'Hello World!',
'str_array' => array(
'en' => 'Hello World!',
'no' => 'Hei Verden!',
),
));
$this->assertEquals($c->getLocalizedString('missing_opt', '--missing--'), '--missing--');
$this->assertEquals($c->getLocalizedString('str_opt'), array('en' => 'Hello World!'));
$this->assertEquals($c->getLocalizedString('str_array'), array('en' => 'Hello World!', 'no' => 'Hei Verden!'));
}
/**
* Test SimpleSAML_Configuration::getLocalizedString() not array nor simple string
* @expectedException Exception
*/
public function testGetLocalizedStringNotArray() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'opt' => 42,
));
$c->getLocalizedString('opt');
}
/**
* Test SimpleSAML_Configuration::getLocalizedString() not string key
* @expectedException Exception
*/
public function testGetLocalizedStringNotStringKey() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'opt' => array(42 => 'text'),
));
$c->getLocalizedString('opt');
}
/**
* Test SimpleSAML_Configuration::getLocalizedString() not string value
* @expectedException Exception
*/
public function testGetLocalizedStringNotStringValue() {
$c = SimpleSAML_Configuration::loadFromArray(array(
'opt' => array('en' => 42),
));
$c->getLocalizedString('opt');
}
/**
* Test that Configuration objects can be initialized from an array.
*
* ATTENTION: this test must be kept the last.
*/
public function testLoadInstanceFromArray()
{
$c = array(
'key' => 'value'
);
// test loading a custom instance
SimpleSAML_Configuration::loadFromArray($c, '', 'dummy');
$this->assertEquals('value', SimpleSAML_Configuration::getInstance('dummy')->getValue('key', null));
// test loading the default instance
SimpleSAML_Configuration::loadFromArray($c, '', 'simplesaml');
$this->assertEquals('value', SimpleSAML_Configuration::getInstance()->getValue('key', null));
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Store/ 0000755 0000000 0000000 00000000000 13245225037 020072 5 ustar root root simplesamlphp-1.15.3/tests/lib/SimpleSAML/Store/SQLTest.php 0000644 0000000 0000000 00000011713 13245225037 022105 0 ustar root root
* @package simplesamlphp/simplesamlphp
*/
class SQLTest extends \PHPUnit_Framework_TestCase
{
protected function setUp()
{
\SimpleSAML_Configuration::loadFromArray(array(
'store.type' => 'sql',
'store.sql.dsn' => 'sqlite::memory:',
'store.sql.prefix' => 'phpunit_',
), '[ARRAY]', 'simplesaml');
}
/**
* @covers \SimpleSAML\Store::getInstance
* @covers \SimpleSAML\Store\SQL::__construct
* @test
*/
public function SQLInstance()
{
$store = Store::getInstance();
$this->assertInstanceOf('SimpleSAML\Store\SQL', $store);
}
/**
* @covers \SimpleSAML\Store\SQL::initTableVersionTable
* @covers \SimpleSAML\Store\SQL::initKVTable
* @test
*/
public function kvstoreTableVersion()
{
/** @var \SimpleSAML\Store\SQL $store */
$store = Store::getInstance();
$version = $store->getTableVersion('kvstore');
$this->assertEquals(1, $version);
}
/**
* @covers \SimpleSAML\Store\SQL::getTableVersion
* @test
*/
public function newTableVersion()
{
/** @var \SimpleSAML\Store\SQL $store */
$store = Store::getInstance();
$version = $store->getTableVersion('test');
$this->assertEquals(0, $version);
}
/**
* @covers \SimpleSAML\Store\SQL::setTableVersion
* @covers \SimpleSAML\Store\SQL::insertOrUpdate
* @test
*/
public function testSetTableVersion()
{
/** @var \SimpleSAML\Store\SQL $store */
$store = Store::getInstance();
$store->setTableVersion('kvstore', 2);
$version = $store->getTableVersion('kvstore');
$this->assertEquals(2, $version);
}
/**
* @covers \SimpleSAML\Store\SQL::get
* @test
*/
public function testGetEmptyData()
{
/** @var \SimpleSAML\Store\SQL $store */
$store = Store::getInstance();
$value = $store->get('test', 'foo');
$this->assertEquals(null, $value);
}
/**
* @covers \SimpleSAML\Store\SQL::get
* @covers \SimpleSAML\Store\SQL::set
* @covers \SimpleSAML\Store\SQL::insertOrUpdate
* @test
*/
public function testInsertData()
{
/** @var \SimpleSAML\Store\SQL $store */
$store = Store::getInstance();
$store->set('test', 'foo', 'bar');
$value = $store->get('test', 'foo');
$this->assertEquals('bar', $value);
}
/**
* @covers \SimpleSAML\Store\SQL::get
* @covers \SimpleSAML\Store\SQL::set
* @covers \SimpleSAML\Store\SQL::insertOrUpdate
* @test
*/
public function testOverwriteData()
{
/** @var \SimpleSAML\Store\SQL $store */
$store = Store::getInstance();
$store->set('test', 'foo', 'bar');
$store->set('test', 'foo', 'baz');
$value = $store->get('test', 'foo');
$this->assertEquals('baz', $value);
}
/**
* @covers \SimpleSAML\Store\SQL::get
* @covers \SimpleSAML\Store\SQL::set
* @covers \SimpleSAML\Store\SQL::insertOrUpdate
* @covers \SimpleSAML\Store\SQL::delete
* @test
*/
public function testDeleteData()
{
/** @var \SimpleSAML\Store\SQL $store */
$store = Store::getInstance();
$store->set('test', 'foo', 'bar');
$store->delete('test', 'foo');
$value = $store->get('test', 'foo');
$this->assertEquals(null, $value);
}
/**
* @covers \SimpleSAML\Store\SQL::get
* @covers \SimpleSAML\Store\SQL::set
* @covers \SimpleSAML\Store\SQL::insertOrUpdate
* @covers \SimpleSAML\Store\SQL::delete
* @test
*/
public function testVeryLongKey()
{
/** @var \SimpleSAML\Store\SQL $store */
$store = Store::getInstance();
$key = str_repeat('x', 100);
$store->set('test', $key, 'bar');
$store->delete('test', $key);
$value = $store->get('test', $key);
$this->assertEquals(null, $value);
}
protected function tearDown()
{
$config = Configuration::getInstance();
$store = Store::getInstance();
$this->clearInstance($config, '\SimpleSAML_Configuration');
$this->clearInstance($store, '\SimpleSAML\Store');
}
protected function clearInstance($service, $className)
{
$reflectedClass = new \ReflectionClass($className);
$reflectedInstance = $reflectedClass->getProperty('instance');
$reflectedInstance->setAccessible(true);
$reflectedInstance->setValue($service, null);
$reflectedInstance->setAccessible(false);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Store/RedisTest.php 0000644 0000000 0000000 00000011220 13245225037 022505 0 ustar root root config = array();
$this->mocked_redis = $this->getMockBuilder('Predis\Client')
->setMethods(array('get', 'set', 'setex', 'del', 'disconnect'))
->disableOriginalConstructor()
->getMock();
$this->mocked_redis->method('get')
->will($this->returnCallback(array($this, 'getMocked')));
$this->mocked_redis->method('set')
->will($this->returnCallback(array($this, 'setMocked')));
$this->mocked_redis->method('setex')
->will($this->returnCallback(array($this, 'setexMocked')));
$this->mocked_redis->method('del')
->will($this->returnCallback(array($this, 'delMocked')));
$nop = function () {
return;
};
$this->mocked_redis->method('disconnect')
->will($this->returnCallback($nop));
$this->redis = new Store\Redis($this->mocked_redis);
}
public function getMocked($key)
{
return array_key_exists($key, $this->config) ? $this->config[$key] : null;
}
public function setMocked($key, $value)
{
$this->config[$key] = $value;
}
public function setexMocked($key, $expire, $value)
{
// Testing expiring data is more trouble than it's worth for now
$this->setMocked($key, $value);
}
public function delMocked($key)
{
unset($this->config[$key]);
}
/**
* @covers \SimpleSAML\Store::getInstance
* @covers \SimpleSAML\Store\Redis::__construct
* @test
*/
public function testRedisInstance()
{
$config = Configuration::loadFromArray(array(
'store.type' => 'redis',
'store.redis.prefix' => 'phpunit_',
), '[ARRAY]', 'simplesaml');
$store = Store::getInstance();
$this->assertInstanceOf('SimpleSAML\Store\Redis', $store);
$this->clearInstance($config, '\SimpleSAML_Configuration');
$this->clearInstance($store, '\SimpleSAML\Store');
}
/**
* @covers \SimpleSAML\Store\Redis::get
* @covers \SimpleSAML\Store\Redis::set
* @test
*/
public function testInsertData()
{
$value = 'TEST';
$this->redis->set('test', 'key', $value);
$res = $this->redis->get('test', 'key');
$expected = $value;
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Store\Redis::get
* @covers \SimpleSAML\Store\Redis::set
* @test
*/
public function testInsertExpiringData()
{
$value = 'TEST';
$this->redis->set('test', 'key', $value, $expire = 80808080);
$res = $this->redis->get('test', 'key');
$expected = $value;
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Store\Redis::get
* @test
*/
public function testGetEmptyData()
{
$res = $this->redis->get('test', 'key');
$this->assertNull($res);
}
/**
* @covers \SimpleSAML\Store\Redis::get
* @covers \SimpleSAML\Store\Redis::set
* @test
*/
public function testOverwriteData()
{
$value1 = 'TEST1';
$value2 = 'TEST2';
$this->redis->set('test', 'key', $value1);
$this->redis->set('test', 'key', $value2);
$res = $this->redis->get('test', 'key');
$expected = $value2;
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Store\Redis::get
* @covers \SimpleSAML\Store\Redis::set
* @covers \SimpleSAML\Store\Redis::delete
* @test
*/
public function testDeleteData()
{
$this->redis->set('test', 'key', 'TEST');
$this->redis->delete('test', 'key');
$res = $this->redis->get('test', 'key');
$this->assertNull($res);
}
protected function clearInstance($service, $className)
{
$reflectedClass = new \ReflectionClass($className);
$reflectedInstance = $reflectedClass->getProperty('instance');
$reflectedInstance->setAccessible(true);
$reflectedInstance->setValue($service, null);
$reflectedInstance->setAccessible(false);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/XML/ 0000755 0000000 0000000 00000000000 13245225037 017436 5 ustar root root simplesamlphp-1.15.3/tests/lib/SimpleSAML/XML/Shib13/ 0000755 0000000 0000000 00000000000 13245225037 020467 5 ustar root root simplesamlphp-1.15.3/tests/lib/SimpleSAML/XML/Shib13/AuthnResponseTest.php 0000644 0000000 0000000 00000006234 13245225037 024643 0 ustar root root
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SimpleSAML\Test\XML\Shib13;
use SimpleSAML\XML\Shib13\AuthnResponse;
class AuthnResponseTest extends \PHPUnit_Framework_TestCase
{
const XMLDOC = <<< XML
NameIdentifier
XML;
const BADXMLDOC = <<< XML
NameIdentifier
XML;
/**
* @var AuthnResponse
*/
private $xml;
protected function setUp()
{
$this->xml = new AuthnResponse();
$this->xml->setXML(static::XMLDOC);
}
/**
* @covers \SimpleSAML\XML\Shib13\AuthnResponse::setXML
* @test
*/
public function setXML()
{
$this->xml = new AuthnResponse();
$this->xml->setXML(static::XMLDOC);
}
/**
* @covers \SimpleSAML\XML\Shib13\AuthnResponse::doXPathQuery
* @covers \SimpleSAML\XML\Shib13\AuthnResponse::getIssuer
* @covers \SimpleSAML\XML\Shib13\AuthnResponse::setXML
* @test
*/
public function getIssuer()
{
$result = $this->xml->getIssuer();
$this->assertEquals(
'Issuer',
$result
);
}
/**
* @covers \SimpleSAML\XML\Shib13\AuthnResponse::getIssuer
* @covers \SimpleSAML\XML\Shib13\AuthnResponse::setXML
* @expectedException \Exception
* @test
*/
public function getIssuerException()
{
$xml = new AuthnResponse();
$xml->setXML(static::BADXMLDOC);
$xml->getIssuer();
}
/**
* @covers \SimpleSAML\XML\Shib13\AuthnResponse::getNameID
* @covers \SimpleSAML\XML\Shib13\AuthnResponse::setXML
* @test
*/
public function getNameID()
{
$result = $this->xml->getNameID();
$this->assertEquals(
array(
'Value' => 'NameIdentifier',
'Format' => 'urn:mace:shibboleth:1.0:nameIdentifier',
),
$result
);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/XML/SignerTest.php 0000644 0000000 0000000 00000022625 13245225037 022245 0 ustar root root root = vfsStream::setup(
self::ROOTDIRNAME,
null,
array(
self::DEFAULTCERTDIR => array(
self::PRIVATEKEY => $this->private_key,
self::CERTIFICATE1 => $this->certificate1,
self::CERTIFICATE2 => $this->certificate2,
),
)
);
$this->root_directory = vfsStream::url(self::ROOTDIRNAME);
$this->certdir = $this->root_directory.DIRECTORY_SEPARATOR.self::DEFAULTCERTDIR;
$this->privatekey_file = $this->certdir.DIRECTORY_SEPARATOR.self::PRIVATEKEY;
$this->certificate_file1 = $this->certdir.DIRECTORY_SEPARATOR.self::CERTIFICATE1;
$this->certificate_file2 = $this->certdir.DIRECTORY_SEPARATOR.self::CERTIFICATE2;
$this->config = Configuration::loadFromArray(array(
'certdir' => $this->certdir,
), '[ARRAY]', 'simplesaml');
}
public function tearDown()
{
$this->clearInstance($this->config, '\SimpleSAML_Configuration', array());
}
public function testSignerBasic()
{
$res = new Signer(array());
$this->assertNotNull($res);
}
public function testSignBasic()
{
$node = new \DOMDocument();
$node->loadXML('value');
$element = $node->getElementsByTagName("node")->item(0);
$doc = new \DOMDocument();
$insertInto = $doc->appendChild(new \DOMElement('insert'));
$signer = new Signer(array());
$signer->loadPrivateKey($this->privatekey_file, null, true);
$signer->sign($element, $insertInto);
$res = $doc->saveXML();
$this->assertContains('DigestValue', $res);
$this->assertContains('SignatureValue', $res);
}
private static function getCertificateValue($certificate)
{
$replacements = array(
"-----BEGIN CERTIFICATE-----",
"-----END CERTIFICATE-----",
"\n",
);
return str_replace($replacements, "", $certificate);
}
public function testSignWithCertificate()
{
$node = new \DOMDocument();
$node->loadXML('value');
$element = $node->getElementsByTagName("node")->item(0);
$doc = new \DOMDocument();
$insertInto = $doc->appendChild(new \DOMElement('insert'));
$signer = new Signer(array());
$signer->loadPrivateKey($this->privatekey_file, null, true);
$signer->loadCertificate($this->certificate_file1, true);
$signer->sign($element, $insertInto);
$res = $doc->saveXML();
$expected = self::getCertificateValue($this->certificate1);
$this->assertContains('X509Certificate', $res);
$this->assertContains($expected, $res);
}
public function testSignWithMultiCertificate()
{
$node = new \DOMDocument();
$node->loadXML('value');
$element = $node->getElementsByTagName("node")->item(0);
$doc = new \DOMDocument();
$insertInto = $doc->appendChild(new \DOMElement('insert'));
$signer = new Signer(array());
$signer->loadPrivateKey($this->privatekey_file, null, true);
$signer->loadCertificate($this->certificate_file1, true);
$signer->addCertificate($this->certificate_file2, true);
$signer->sign($element, $insertInto);
$res = $doc->saveXML();
$expected1 = self::getCertificateValue($this->certificate1);
$expected2 = self::getCertificateValue($this->certificate2);
$this->assertContains('X509Certificate', $res);
$this->assertContains($expected1, $res);
$this->assertContains($expected2, $res);
}
public function testSignMissingPrivateKey()
{
$node = new \DOMDocument();
$node->loadXML('value');
$element = $node->getElementsByTagName("node")->item(0);
$doc = new \DOMDocument();
$insertInto = $doc->appendChild(new \DOMElement('insert'));
$signer = new Signer(array());
$this->setExpectedException('\Exception');
$signer->sign($element, $insertInto);
}
protected function clearInstance($service, $className, $value = null)
{
$reflectedClass = new \ReflectionClass($className);
$reflectedInstance = $reflectedClass->getProperty('instance');
$reflectedInstance->setAccessible(true);
$reflectedInstance->setValue($service, $value);
$reflectedInstance->setAccessible(false);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/XML/ParserTest.php 0000644 0000000 0000000 00000006137 13245225037 022252 0 ustar root root
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SimpleSAML\Test\XML;
use SimpleSAML\XML\Parser;
class ParserTest extends \PHPUnit_Framework_TestCase
{
const XMLDOC = <<< XML
Hello, World!
XML;
/** @var Parser */
private $xml;
protected function setUp()
{
$this->xml = new Parser(static::XMLDOC);
}
/**
* @covers \SimpleSAML\XML\Parser::getValue
* @covers \SimpleSAML\XML\Parser::__construct
* @test
*/
public function getValue()
{
$result = $this->xml->getValue('/Root/Value', true);
$this->assertEquals(
'Hello, World!',
$result
);
}
/**
* @covers \SimpleSAML\XML\Parser::getValue
* @covers \SimpleSAML\XML\Parser::__construct
* @test
*/
public function getEmptyValue()
{
$result = $this->xml->getValue('/Root/Foo', false);
$this->assertEquals(
null,
$result
);
}
/**
* @covers \SimpleSAML\XML\Parser::getValue
* @covers \SimpleSAML\XML\Parser::__construct
* @expectedException \Exception
* @test
*/
public function getValueException()
{
$this->xml->getValue('/Root/Foo', true);
}
/**
* @covers \SimpleSAML\XML\Parser::getValueDefault
* @covers \SimpleSAML\XML\Parser::__construct
* @test
*/
public function getDefaultValue()
{
$result = $this->xml->getValueDefault('/Root/Other', 'Hello');
$this->assertEquals(
'Hello',
$result
);
}
/**
* @covers \SimpleSAML\XML\Parser::getValueAlternatives
* @covers \SimpleSAML\XML\Parser::__construct
* @test
*/
public function getValueAlternatives()
{
$result = $this
->xml
->getValueAlternatives(array(
'/Root/Other',
'/Root/Value'
), true)
;
$this->assertEquals(
'Hello, World!',
$result
);
}
/**
* @covers \SimpleSAML\XML\Parser::getValueAlternatives
* @covers \SimpleSAML\XML\Parser::__construct
* @test
*/
public function getEmptyValueAlternatives()
{
$result = $this
->xml
->getValueAlternatives(array(
'/Root/Foo',
'/Root/Bar'
), false)
;
$this->assertEquals(
null,
$result
);
}
/**
* @covers \SimpleSAML\XML\Parser::getValueAlternatives
* @covers \SimpleSAML\XML\Parser::__construct
* @expectedException \Exception
* @test
*/
public function getValueAlternativesException()
{
$this
->xml
->getValueAlternatives(array(
'/Root/Foo',
'/Root/Bar'
), true)
;
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/XML/ErrorsTest.php 0000644 0000000 0000000 00000003027 13245225037 022265 0 ustar root root
* @package simplesamlphp/simplesamlphp
*/
namespace SimpleSAML\Test\XML;
use SimpleSAML\XML\Errors;
class ErrorsTest extends \PHPUnit_Framework_TestCase
{
/**
* @covers \SimpleSAML\XML\Errors::begin
* @covers \SimpleSAML\XML\Errors::addErrors
* @covers \SimpleSAML\XML\Errors::end
* @test
*/
public function loggingErrors()
{
Errors::begin();
$xmlstr = "Test";
simplexml_load_string($xmlstr);
$errors = Errors::end();
$errors = Errors::formatErrors($errors);
$this->assertEquals(
"level=3,code=76,line=1,col=18,msg=Opening and ending tag mismatch: Test line 1 and test\n",
$errors
);
}
/**
* @covers \SimpleSAML\XML\Errors::formatError
* @covers \SimpleSAML\XML\Errors::formatErrors
* @test
*/
public function formatErrors()
{
$error = new \LibXMLError();
$error->level = 'level';
$error->code = 'code';
$error->line = 'line';
$error->column = 'col';
$error->message = ' msg ';
$errors = Errors::formatErrors(array($error, $error));
$this->assertEquals(
"level=level,code=code,line=line,col=col,msg=msg\nlevel=level,code=code,line=line,col=col,msg=msg\n",
$errors
);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Auth/ 0000755 0000000 0000000 00000000000 13245225037 017677 5 ustar root root simplesamlphp-1.15.3/tests/lib/SimpleSAML/Auth/TimeLimitedTokenTest.php 0000644 0000000 0000000 00000004540 13245225037 024462 0 ustar root root 'random'), '[ARRAY]', 'simplesaml');
$token = new TimeLimitedToken();
$this->assertFalse($token->validate('malformed'));
$this->assertFalse($token->validate('mal-for-med'));
$this->assertFalse($token->validate('mal-formed'));
}
/**
* Basic test to see if validation works for valid tokens.
*/
public function testValidToken()
{
\SimpleSAML_Configuration::loadFromArray(array('secretsalt' => 'random'), '[ARRAY]', 'simplesaml');
$token = new TimeLimitedToken();
$t = $token->generate();
$this->assertTrue($token->validate($t));
}
/**
* Test that token validation takes the verification data into account.
*/
public function testValidTokenWithData()
{
\SimpleSAML_Configuration::loadFromArray(array('secretsalt' => 'random'), '[ARRAY]', 'simplesaml');
$tokenWithData = new TimeLimitedToken();
$tokenWithData->addVerificationData('some more random data');
$t = $tokenWithData->generate();
$this->assertTrue($tokenWithData->validate($t));
$tokenWithoutData = new TimeLimitedToken();
$this->assertFalse($tokenWithoutData->validate($t));
}
/**
* Test that expired tokens are rejected.
*/
public function testExpiredToken()
{
\SimpleSAML_Configuration::loadFromArray(array('secretsalt' => 'random'), '[ARRAY]', 'simplesaml');
$token = new TimeLimitedToken();
$this->assertFalse($token->validate('7-c0803e76fff1df0ceb222dee80aa1d73f35d84dd'));
}
/**
* Test that a token that has been manipulated to extend its validity is rejected.
*/
public function testManipulatedToken()
{
\SimpleSAML_Configuration::loadFromArray(array('secretsalt' => 'random'), '[ARRAY]', 'simplesaml');
$token = new TimeLimitedToken(1);
$t = $token->generate();
list($offset, $hash) = explode('-', $t);
sleep(1);
$this->assertFalse($token->validate(dechex(hexdec($offset) + 1).'-'.$hash));
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Auth/SimpleTest.php 0000644 0000000 0000000 00000006420 13245225037 022503 0 ustar root root getMethod('getProcessedURL');
$method->setAccessible(true);
// fool the routines to make them believe we are running in a web server
$_SERVER['REQUEST_URI'] = '/';
// test merging configuration option with passed URL
\SimpleSAML_Configuration::loadFromArray(array(
'application' => array(
'baseURL' => 'https://example.org'
)
), '[ARRAY]', 'simplesaml');
$s = new \SimpleSAML\Auth\Simple('');
$this->assertEquals('https://example.org/', $method->invokeArgs($s, array(null)));
// test a full URL passed as parameter
$this->assertEquals(
'https://example.org/foo/bar?a=b#fragment',
$method->invokeArgs(
$s,
array('http://some.overridden.host/foo/bar?a=b#fragment')
)
);
// test a full, current URL with no parameters
$_SERVER['REQUEST_URI'] = '/foo/bar?a=b#fragment';
$this->assertEquals('https://example.org/foo/bar?a=b#fragment', $method->invokeArgs($s, array(null)));
// test ports are overridden by configuration
$_SERVER['SERVER_PORT'] = '1234';
$this->assertEquals('https://example.org/foo/bar?a=b#fragment', $method->invokeArgs($s, array(null)));
// test config option with ending with / and port
\SimpleSAML_Configuration::loadFromArray(array(
'application' => array(
'baseURL' => 'http://example.org:8080/'
)
), '[ARRAY]', 'simplesaml');
$s = new \SimpleSAML\Auth\Simple('');
$this->assertEquals('http://example.org:8080/foo/bar?a=b#fragment', $method->invokeArgs($s, array(null)));
// test again with a relative URL as a parameter
$this->assertEquals(
'http://example.org:8080/something?foo=bar#something',
$method->invokeArgs($s, array('/something?foo=bar#something'))
);
// now test with no configuration
$_SERVER['SERVER_NAME'] = 'example.org';
\SimpleSAML_Configuration::loadFromArray(array(), '[ARRAY]', 'simplesaml');
$s = new \SimpleSAML\Auth\Simple('');
$this->assertEquals('http://example.org:1234/foo/bar?a=b#fragment', $method->invokeArgs($s, array(null)));
// no configuration, https and port
$_SERVER['HTTPS'] = 'on';
$this->assertEquals('https://example.org:1234/foo/bar?a=b#fragment', $method->invokeArgs($s, array(null)));
// no configuration and a relative URL as a parameter
$this->assertEquals(
'https://example.org:1234/something?foo=bar#something',
$method->invokeArgs($s, array('/something?foo=bar#something'))
);
// finally, no configuration and full URL as a parameter
$this->assertEquals(
'https://example.org/one/two/three?foo=bar#fragment',
$method->invokeArgs($s, array('https://example.org/one/two/three?foo=bar#fragment'))
);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Auth/StateTest.php 0000644 0000000 0000000 00000004725 13245225037 022340 0 ustar root root array(),
'Expire' => 1234,
'LogoutState' => 'logoutState',
'AuthInstant' => 123456,
'RememberMe' => true,
'saml:sp:NameID' => 'nameID',
);
// check just mandatory parameters
$state = $mandatory;
$expected = $mandatory;
$this->assertEquals(
$expected,
SimpleSAML_Auth_State::getPersistentAuthData($state),
'Mandatory state attributes did not survive as expected'.print_r($expected, true)
);
// check missing mandatory parameters
unset($state['LogoutState']);
unset($state['RememberMe']);
$expected = $state;
$this->assertEquals(
$expected,
SimpleSAML_Auth_State::getPersistentAuthData($state),
'Some error occurred with missing mandatory parameters'
);
// check additional non-persistent parameters
$additional = array(
'additional1' => 1,
'additional2' => 2,
);
$state = array_merge($mandatory, $additional);
$expected = $mandatory;
$this->assertEquals(
$expected,
SimpleSAML_Auth_State::getPersistentAuthData($state),
'Additional parameters survived'
);
// check additional persistent parameters
$additional['PersistentAuthData'] = array('additional1');
$state = array_merge($mandatory, $additional);
$expected = $state;
unset($expected['additional2']);
unset($expected['PersistentAuthData']);
$this->assertEquals(
$expected,
SimpleSAML_Auth_State::getPersistentAuthData($state),
'Some error occurred with additional, persistent parameters'
);
// check only additional persistent parameters
$state = $additional;
$expected = $state;
unset($expected['additional2']);
unset($expected['PersistentAuthData']);
$this->assertEquals(
$expected,
SimpleSAML_Auth_State::getPersistentAuthData($state),
'Some error occurred with additional, persistent parameters, and no mandatory ones'
);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/DatabaseTest.php 0000644 0000000 0000000 00000023227 13245225037 022061 0 ustar root root
* @package SimpleSAMLphp
*/
class SimpleSAML_DatabaseTest extends PHPUnit_Framework_TestCase
{
/**
* @var SimpleSAML_Configuration
*/
protected $config;
/**
* @var SimpleSAML\Database
*/
protected $db;
/**
* Make protected functions available for testing
*
* @param string $getMethod The method to get.
* @requires PHP 5.3.2
*
* @return mixed The method itself.
*/
protected static function getMethod($getMethod)
{
$class = new ReflectionClass('SimpleSAML\Database');
$method = $class->getMethod($getMethod);
$method->setAccessible(true);
return $method;
}
/**
* @covers SimpleSAML\Database::getInstance
* @covers SimpleSAML\Database::generateInstanceId
* @covers SimpleSAML\Database::__construct
* @covers SimpleSAML\Database::connect
*/
public function setUp()
{
$config = array(
'database.dsn' => 'sqlite::memory:',
'database.username' => null,
'database.password' => null,
'database.prefix' => 'phpunit_',
'database.persistent' => true,
'database.slaves' => array(),
);
$this->config = new SimpleSAML_Configuration($config, "test/SimpleSAML/DatabaseTest.php");
// Ensure that we have a functional configuration class
$this->assertInstanceOf('SimpleSAML_Configuration', $this->config);
$this->assertEquals($config['database.dsn'], $this->config->getString('database.dsn'));
$this->db = SimpleSAML\Database::getInstance($this->config);
// Ensure that we have a functional database class.
$this->assertInstanceOf('SimpleSAML\Database', $this->db);
}
/**
* @covers SimpleSAML\Database::getInstance
* @covers SimpleSAML\Database::generateInstanceId
* @covers SimpleSAML\Database::__construct
* @covers SimpleSAML\Database::connect
* @expectedException Exception
* @test
*/
public function connectionFailure()
{
$config = array(
'database.dsn' => 'mysql:host=localhost;dbname=saml',
'database.username' => 'notauser',
'database.password' => 'notausersinvalidpassword',
'database.prefix' => 'phpunit_',
'database.persistent' => true,
'database.slaves' => array(),
);
$this->config = new SimpleSAML_Configuration($config, "test/SimpleSAML/DatabaseTest.php");
$db = SimpleSAML\Database::getInstance($this->config);
}
/**
* @covers SimpleSAML\Database::getInstance
* @covers SimpleSAML\Database::generateInstanceId
* @covers SimpleSAML\Database::__construct
* @covers SimpleSAML\Database::connect
* @test
*/
public function instances()
{
$config = array(
'database.dsn' => 'sqlite::memory:',
'database.username' => null,
'database.password' => null,
'database.prefix' => 'phpunit_',
'database.persistent' => true,
'database.slaves' => array(),
);
$config2 = array(
'database.dsn' => 'sqlite::memory:',
'database.username' => null,
'database.password' => null,
'database.prefix' => 'phpunit2_',
'database.persistent' => true,
'database.slaves' => array(),
);
$config1 = new SimpleSAML_Configuration($config, "test/SimpleSAML/DatabaseTest.php");
$config2 = new SimpleSAML_Configuration($config2, "test/SimpleSAML/DatabaseTest.php");
$config3 = new SimpleSAML_Configuration($config, "test/SimpleSAML/DatabaseTest.php");
$db1 = SimpleSAML\Database::getInstance($config1);
$db2 = SimpleSAML\Database::getInstance($config2);
$db3 = SimpleSAML\Database::getInstance($config3);
$generateInstanceId = self::getMethod('generateInstanceId');
$instance1 = $generateInstanceId->invokeArgs($db1, array($config1));
$instance2 = $generateInstanceId->invokeArgs($db2, array($config2));
$instance3 = $generateInstanceId->invokeArgs($db3, array($config3));
// Assert that $instance1 and $instance2 have different instance ids
$this->assertNotEquals(
$instance1,
$instance2,
"Database instances should be different, but returned the same id"
);
// Assert that $instance1 and $instance3 have identical instance ids
$this->assertEquals(
$instance1,
$instance3,
"Database instances should have the same id, but returned different id"
);
// Assert that $db1 and $db2 are different instances
$this->assertNotEquals(
spl_object_hash($db1),
spl_object_hash($db2),
"Database instances should be different, but returned the same spl_object_hash"
);
// Assert that $db1 and $db3 are identical instances
$this->assertEquals(
spl_object_hash($db1),
spl_object_hash($db3),
"Database instances should be the same, but returned different spl_object_hash"
);
}
/**
* @covers SimpleSAML\Database::getInstance
* @covers SimpleSAML\Database::generateInstanceId
* @covers SimpleSAML\Database::__construct
* @covers SimpleSAML\Database::connect
* @covers SimpleSAML\Database::getSlave
* @test
*/
public function slaves()
{
$getSlave = self::getMethod('getSlave');
$master = spl_object_hash(PHPUnit_Framework_Assert::readAttribute($this->db, 'dbMaster'));
$slave = spl_object_hash($getSlave->invokeArgs($this->db, array()));
$this->assertTrue(($master == $slave), "getSlave should have returned the master database object");
$config = array(
'database.dsn' => 'sqlite::memory:',
'database.username' => null,
'database.password' => null,
'database.prefix' => 'phpunit_',
'database.persistent' => true,
'database.slaves' => array(
array(
'dsn' => 'sqlite::memory:',
'username' => null,
'password' => null,
),
),
);
$sspConfiguration = new SimpleSAML_Configuration($config, "test/SimpleSAML/DatabaseTest.php");
$msdb = SimpleSAML\Database::getInstance($sspConfiguration);
$slaves = PHPUnit_Framework_Assert::readAttribute($msdb, 'dbSlaves');
$gotSlave = spl_object_hash($getSlave->invokeArgs($msdb, array()));
$this->assertEquals(
spl_object_hash($slaves[0]),
$gotSlave,
"getSlave should have returned a slave database object"
);
}
/**
* @covers SimpleSAML\Database::applyPrefix
* @test
*/
public function prefix()
{
$prefix = $this->config->getString('database.prefix');
$table = "saml20_idp_hosted";
$pftable = $this->db->applyPrefix($table);
$this->assertEquals($prefix.$table, $pftable, "Did not properly apply the table prefix");
}
/**
* @covers SimpleSAML\Database::write
* @covers SimpleSAML\Database::read
* @covers SimpleSAML\Database::exec
* @covers SimpleSAML\Database::query
* @test
*/
public function querying()
{
$table = $this->db->applyPrefix("sspdbt");
$this->assertEquals($this->config->getString('database.prefix')."sspdbt", $table);
$this->db->write(
"CREATE TABLE IF NOT EXISTS $table (ssp_key INT(16) NOT NULL, ssp_value TEXT NOT NULL)",
false
);
$query1 = $this->db->read("SELECT * FROM $table");
$this->assertEquals(0, $query1->fetch(), "Table $table is not empty when it should be.");
$ssp_key = time();
$ssp_value = md5(rand(0, 10000));
$stmt = $this->db->write(
"INSERT INTO $table (ssp_key, ssp_value) VALUES (:ssp_key, :ssp_value)",
array('ssp_key' => array($ssp_key, PDO::PARAM_INT), 'ssp_value' => $ssp_value)
);
$this->assertEquals(1, $stmt, "Could not insert data into $table.");
$query2 = $this->db->read("SELECT * FROM $table WHERE ssp_key = :ssp_key", array('ssp_key' => $ssp_key));
$data = $query2->fetch();
$this->assertEquals($data['ssp_value'], $ssp_value, "Inserted data doesn't match what is in the database");
}
/**
* @covers SimpleSAML\Database::read
* @covers SimpleSAML\Database::query
* @expectedException Exception
* @test
*/
public function readFailure()
{
$table = $this->db->applyPrefix("sspdbt");
$this->assertEquals($this->config->getString('database.prefix')."sspdbt", $table);
$this->db->read("SELECT * FROM $table");
}
/**
* @covers SimpleSAML\Database::write
* @covers SimpleSAML\Database::exec
* @expectedException Exception
* @test
*/
public function noSuchTable()
{
$this->db->write("DROP TABLE phpunit_nonexistent", false);
}
public function tearDown()
{
$table = $this->db->applyPrefix("sspdbt");
$this->db->write("DROP TABLE IF EXISTS $table", false);
unset($this->config);
unset($this->db);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/ModuleTest.php 0000644 0000000 0000000 00000006511 13245225037 021577 0 ustar root root assertTrue(Module::isModuleEnabled('core'));
}
/**
* Test for SimpleSAML\Module::getModuleDir().
*/
public function testGetModuleDir()
{
// test for the most basic functionality
$this->assertEquals(
dirname(dirname(dirname(dirname(__FILE__)))).'/modules/module',
Module::getModuleDir('module')
);
}
/**
* Test for SimpleSAML\Module::getModuleURL().
*/
public function testGetModuleURL()
{
\SimpleSAML_Configuration::loadFromArray(array(
'baseurlpath' => 'https://example.com/simplesaml/'
), '', 'simplesaml');
$this->assertEquals(
'https://example.com/simplesaml/module.php/module/script.php',
Module::getModuleURL('module/script.php')
);
$this->assertEquals(
'https://example.com/simplesaml/module.php/module/script.php?param1=value1¶m2=value2',
Module::getModuleURL('module/script.php', array(
'param1' => 'value1',
'param2' => 'value2',
))
);
}
/**
* Test for SimpleSAML\Module::getModules().
*/
public function testGetModules()
{
$this->assertGreaterThan(0, count(Module::getModules()));
}
/**
* Test for SimpleSAML\Module::resolveClass(). It will make sure that an exception is thrown if we are not asking
* for a class inside a module (that is, there is no colon separating the name of the module and the name of the
* class).
*
* @expectedException \Exception
*/
public function testResolveClassNoModule()
{
Module::resolveClass('nomodule', '');
}
/**
* Test for SimpleSAML\Module::resolveClass(). It will make sure that an exception is thrown if the class we are
* asking for cannot be found.
*
* @expectedException \Exception
*/
public function testResolveClassNotFound()
{
Module::resolveClass('core:Missing', '');
}
/**
* Test for SimpleSAML\Module::resolveClass(). It will make sure that an exception is thrown if the class we are
* asking for can be resolved, but does not extend a given class.
*
* @expectedException \Exception
*/
public function testResolveClassNotSubclass()
{
Module::resolveClass('core:PHP', 'Auth_Process', '\Exception');
}
/**
* Test for SimpleSAML\Module::resolveClass(). It covers all the valid use cases.
*/
public function tesstResolveClass()
{
// most basic test
$this->assertEquals('sspmod_core_ACL', Module::resolveClass('core:ACL', ''));
// test for the $type parameter correctly translated into a path
$this->assertEquals('sspmod_core_Auth_Process_PHP', Module::resolveClass('core:PHP', 'Auth_Process'));
// test for valid subclasses
$this->assertEquals('sspmod_core_Auth_Process_PHP', Module::resolveClass(
'core:PHP',
'Auth_Process',
'SimpleSAML_Auth_ProcessingFilter'
));
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Locale/ 0000755 0000000 0000000 00000000000 13245225037 020175 5 ustar root root simplesamlphp-1.15.3/tests/lib/SimpleSAML/Locale/LanguageTest.php 0000644 0000000 0000000 00000012652 13245225037 023277 0 ustar root root assertEquals('en', $l->getDefaultLanguage());
// test defaults coming from configuration
$c = \SimpleSAML_Configuration::loadFromArray(array(
'language.available' => array('en', 'es', 'nn'),
'language.default' => 'es',
));
$l = new Language($c);
$this->assertEquals('es', $l->getDefaultLanguage());
}
/**
* Test SimpleSAML\Locale\Language::getLanguageCookie().
*/
public function testGetLanguageCookie()
{
// test it works when no cookie is set
\SimpleSAML_Configuration::loadFromArray(array(), '', 'simplesaml');
$this->assertNull(Language::getLanguageCookie());
// test that it works fine with defaults
\SimpleSAML_Configuration::loadFromArray(array(), '', 'simplesaml');
$_COOKIE['language'] = 'en';
$this->assertEquals('en', Language::getLanguageCookie());
// test that it works with non-defaults
\SimpleSAML_Configuration::loadFromArray(array(
'language.available' => array('en', 'es', 'nn'),
'language.cookie.name' => 'xyz'
), '', 'simplesaml');
$_COOKIE['xyz'] = 'Es'; // test values are converted to lowercase too
$this->assertEquals('es', Language::getLanguageCookie());
}
/**
* Test SimpleSAML\Locale\Language::getLanguageList().
*/
public function testGetLanguageListNoConfig()
{
// test defaults
$c = \SimpleSAML_Configuration::loadFromArray(array(), '', 'simplesaml');
$l = new Language($c);
$l->setLanguage('en');
$this->assertEquals(array('en' => true), $l->getLanguageList());
}
/**
* Test SimpleSAML\Locale\Language::getLanguageList().
*/
public function testGetLanguageListCorrectConfig()
{
// test langs from from language_names
$c = \SimpleSAML_Configuration::loadFromArray(array(
'language.available' => array('en', 'nn', 'es'),
), '', 'simplesaml');
$l = new Language($c);
$l->setLanguage('es');
$this->assertEquals(array(
'en' => false,
'es' => true,
'nn' => false,
), $l->getLanguageList());
}
/**
* Test SimpleSAML\Locale\Language::getLanguageList().
*/
public function testGetLanguageListIncorrectConfig()
{
// test non-existent langs
$c = \SimpleSAML_Configuration::loadFromArray(array(
'language.available' => array('foo', 'bar'),
), '', 'simplesaml');
$l = new Language($c);
$l->setLanguage('foo');
$this->assertEquals(array('en' => true), $l->getLanguageList());
}
/**
* Test SimpleSAML\Locale\Language::getLanguageParameterName().
*/
public function testGetLanguageParameterName()
{
// test for default configuration
$c = \SimpleSAML_Configuration::loadFromArray(array(), '', 'simplesaml');
$l = new Language($c);
$this->assertEquals('language', $l->getLanguageParameterName());
// test for valid configuration
$c = \SimpleSAML_Configuration::loadFromArray(array(
'language.parameter.name' => 'xyz'
), '', 'simplesaml');
$l = new Language($c);
$this->assertEquals('xyz', $l->getLanguageParameterName());
}
/**
* Test SimpleSAML\Locale\Language::isLanguageRTL().
*/
public function testIsLanguageRTL()
{
// test defaults
$c = \SimpleSAML_Configuration::loadFromArray(array(), '', 'simplesaml');
$l = new Language($c);
$l->setLanguage('en');
$this->assertFalse($l->isLanguageRTL());
// test non-defaults, non-RTL
$c = \SimpleSAML_Configuration::loadFromArray(array(
'language.rtl' => array('foo', 'bar'),
), '', 'simplesaml');
$l = new Language($c);
$l->setLanguage('en');
$this->assertFalse($l->isLanguageRTL());
// test non-defaults, RTL
$c = \SimpleSAML_Configuration::loadFromArray(array(
'language.available' => array('en', 'nn', 'es'),
'language.rtl' => array('nn', 'es'),
), '', 'simplesaml');
$l = new Language($c);
$l->setLanguage('es');
$this->assertTrue($l->isLanguageRTL());
}
/**
* Test SimpleSAML\Locale\Language::setLanguage().
*/
public function testSetLanguage()
{
// test with valid configuration, no cookies set
$c = \SimpleSAML_Configuration::loadFromArray(array(
'language.available' => array('en', 'nn', 'es'),
'language.parameter.name' => 'xyz',
'language.parameter.setcookie' => false,
), '', 'simplesaml');
$_GET['xyz'] = 'Es'; // test also that lang code is transformed to lower caps
$l = new Language($c);
$this->assertEquals('es', $l->getLanguage());
// test with valid configuration, no cookies, language set unavailable
$_GET['xyz'] = 'unavailable';
$l = new Language($c);
$this->assertEquals('en', $l->getLanguage());
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Locale/TranslateTest.php 0000644 0000000 0000000 00000001734 13245225037 023510 0 ustar root root assertEquals($testString, $t->noop($testString));
}
/**
* Test SimpleSAML\Locale\Translate::t().
*/
public function testTFallback()
{
$c = \SimpleSAML_Configuration::loadFromArray(array());
$t = new Translate($c);
$testString = 'Blablabla';
// $fallbackdefault = true
$result = 'not translated ('.$testString.')';
$this->assertEquals($result, $t->t($testString));
// $fallbackdefault = false, should be a noop
$this->assertEquals($testString, $t->t($testString, array(), false));
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Locale/LocalizationTest.php 0000644 0000000 0000000 00000002757 13245225037 024211 0 ustar root root 'SimpleSAMLphp')
);
$l = new Localization($c);
$this->assertTrue($l->isI18NBackendDefault());
$this->assertEquals(Localization::DEFAULT_DOMAIN, 'messages');
}
/**
* Test SimpleSAML\Locale\Localization::activateDomain().
*/
public function testAddDomain()
{
$c = \SimpleSAML_Configuration::loadFromArray(
array('language.i18n.backend' => 'gettext/gettext')
);
$l = new Localization($c);
$newDomain = 'test';
$newDomainLocaleDir = $l->getLocaleDir();
$l->addDomain($newDomainLocaleDir, $newDomain);
$registeredDomains = $l->getRegisteredDomains();
$this->assertArrayHasKey($newDomain, $registeredDomains);
$this->assertEquals($registeredDomains[$newDomain], $newDomainLocaleDir);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Utils/ 0000755 0000000 0000000 00000000000 13245225037 020076 5 ustar root root simplesamlphp-1.15.3/tests/lib/SimpleSAML/Utils/TimeTest.php 0000644 0000000 0000000 00000014271 13245225037 022352 0 ustar root root assertEquals('2016-03-03T14:48:05Z', Time::generateTimestamp(1457016485));
// test timestamp generation for current time
$this->assertRegExp('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/', Time::generateTimestamp());
}
/**
* Test the SimpleSAML\Utils\Time::initTimezone() method.
*
* @covers SimpleSAML\Utils\Time::initTimezone
*/
public function testInitTimezone()
{
$tz = 'UTC';
$os = @date_default_timezone_get();
if ($os === 'UTC') { // avoid collisions
$tz = 'Europe/Oslo';
}
// test guessing timezone from the OS
\SimpleSAML_Configuration::loadFromArray(array('timezone' => null), '[ARRAY]', 'simplesaml');
@Time::initTimezone();
$this->assertEquals($os, @date_default_timezone_get());
// clear initialization
$c = new \ReflectionProperty('\SimpleSAML\Utils\Time', 'tz_initialized');
$c->setAccessible(true);
$c->setValue(false);
// test unknown timezone
\SimpleSAML_Configuration::loadFromArray(array('timezone' => 'INVALID'), '[ARRAY]', 'simplesaml');
try {
@Time::initTimezone();
$this->fail('Failed to recognize an invalid timezone.');
} catch (\SimpleSAML_Error_Exception $e) {
$this->assertEquals('Invalid timezone set in the "timezone" option in config.php.', $e->getMessage());
}
// test a valid timezone
\SimpleSAML_Configuration::loadFromArray(array('timezone' => $tz), '[ARRAY]', 'simplesaml');
@Time::initTimezone();
$this->assertEquals($tz, @date_default_timezone_get());
// make sure initialization happens only once
\SimpleSAML_Configuration::loadFromArray(array('timezone' => 'Europe/Madrid'), '[ARRAY]', 'simplesaml');
@Time::initTimezone();
$this->assertEquals($tz, @date_default_timezone_get());
}
/**
* Test the SimpleSAML\Utils\Time::parseDuration() method.
*
* @covers SimpleSAML\Utils\Time::parseDuration
*/
public function testParseDuration()
{
// set up base date and time, and fixed durations from there
$base = gmmktime(0, 0, 0, 1, 1, 2000);
$second = gmmktime(0, 0, 1, 1, 1, 2000); // +1 sec
$minute = gmmktime(0, 1, 0, 1, 1, 2000); // +1 min
$hour = gmmktime(1, 0, 0, 1, 1, 2000); // +1 hour
$day = gmmktime(0, 0, 0, 1, 2, 2000); // +1 day
$week = gmmktime(0, 0, 0, 1, 8, 2000); // +1 week
$month = gmmktime(0, 0, 0, 2, 1, 2000); // +1 month
$year = gmmktime(0, 0, 0, 1, 1, 2001); // +1 year
// corner cases
$manymonths = gmmktime(0, 0, 0, 3, 1, 2001); // +14 months = +1 year +2 months
$negmonths = gmmktime(0, 0, 0, 10, 1, 1999); // -3 months = -1 year +9 months
// test valid duration with timestamp and zeroes
$this->assertEquals($base + (60 * 60) + 60 + 1, Time::parseDuration('P0Y0M0DT1H1M1S', $base));
// test seconds
$this->assertEquals($second, Time::parseDuration('PT1S', $base), "Failure checking for 1 second duration.");
// test minutes
$this->assertEquals($minute, Time::parseDuration('PT1M', $base), "Failure checking for 1 minute duration.");
// test hours
$this->assertEquals($hour, Time::parseDuration('PT1H', $base), "Failure checking for 1 hour duration.");
// test days
$this->assertEquals($day, Time::parseDuration('P1D', $base), "Failure checking for 1 day duration.");
// test weeks
$this->assertEquals($week, Time::parseDuration('P1W', $base), "Failure checking for 1 week duration.");
// test month
$this->assertEquals($month, Time::parseDuration('P1M', $base), "Failure checking for 1 month duration.");
// test year
$this->assertEquals($year, Time::parseDuration('P1Y', $base), "Failure checking for 1 year duration.");
// test months > 12
$this->assertEquals(
$manymonths,
Time::parseDuration('P14M', $base),
"Failure checking for 14 months duration (1 year and 2 months)."
);
// test negative months
$this->assertEquals(
$negmonths,
Time::parseDuration('-P3M', $base),
"Failure checking for -3 months duration (-1 year + 9 months)."
);
// test from current time
$now = time();
$this->assertGreaterThanOrEqual(
$now + 60,
Time::parseDuration('PT1M'),
"Failure testing for 1 minute over current time."
);
// test invalid input parameters
try {
// invalid duration
Time::parseDuration(0);
$this->fail("Did not fail with invalid duration parameter.");
} catch (\InvalidArgumentException $e) {
$this->assertEquals('Invalid input parameters', $e->getMessage());
}
try {
// invalid timestamp
Time::parseDuration('', array());
$this->fail("Did not fail with invalid timestamp parameter.");
} catch (\InvalidArgumentException $e) {
$this->assertEquals('Invalid input parameters', $e->getMessage());
}
// test invalid durations
try {
// invalid string
Time::parseDuration('abcdefg');
$this->fail("Did not fail with invalid ISO 8601 duration.");
} catch (\InvalidArgumentException $e) {
$this->assertStringStartsWith('Invalid ISO 8601 duration: ', $e->getMessage());
}
try {
// missing T delimiter
Time::parseDuration('P1S');
$this->fail("Did not fail with duration missing T delimiter.");
} catch (\InvalidArgumentException $e) {
$this->assertStringStartsWith('Invalid ISO 8601 duration: ', $e->getMessage());
}
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Utils/RandomTest.php 0000644 0000000 0000000 00000001110 13245225037 022660 0 ustar root root assertStringStartsWith('_', Random::generateID());
// check the length
$this->assertEquals(Random::ID_LENGTH, strlen(Random::generateID()));
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Utils/NetTest.php 0000644 0000000 0000000 00000007236 13245225037 022205 0 ustar root root assertFalse(Net::ipCIDRcheck('127.0.0.0', '127.0.0.1'));
// check wrong CIDR w/ mask
$this->assertFalse(Net::ipCIDRcheck('127.0.0.256/24', '127.0.0.1'));
// check wrong IP
$this->assertFalse(Net::ipCIDRcheck('127.0.0.0/24', '127.0.0'));
$this->assertFalse(Net::ipCIDRcheck('127.0.0.0/24', '127.0.0.*'));
// check limits for standard classes
$this->assertTrue(Net::ipCIDRcheck('127.0.0.0/24', '127.0.0.0'));
$this->assertTrue(Net::ipCIDRcheck('127.0.0.0/24', '127.0.0.255'));
$this->assertFalse(Net::ipCIDRcheck('127.0.0.0/24', '127.0.0.256'));
$this->assertTrue(Net::ipCIDRcheck('127.0.0.0/16', '127.0.0.0'));
$this->assertTrue(Net::ipCIDRcheck('127.0.0.0/16', '127.0.255.255'));
$this->assertFalse(Net::ipCIDRcheck('127.0.0.0/16', '127.0.255.256'));
$this->assertFalse(Net::ipCIDRcheck('127.0.0.0/16', '127.0.256.255'));
// check limits for non-standard classes
$this->assertTrue(Net::ipCIDRcheck('127.0.0.0/23', '127.0.0.0'));
$this->assertTrue(Net::ipCIDRcheck('127.0.0.0/23', '127.0.1.255'));
$this->assertFalse(Net::ipCIDRcheck('127.0.0.0/23', '127.0.1.256'));
$this->assertFalse(Net::ipCIDRcheck('127.0.0.0/23', '127.0.2.0'));
}
/**
* Test IPv6 support in SimpleSAML\Utils\Net::ipCIDRcheck.
*
* @covers SimpleSAML\Utils\Net::ipCIDRcheck
*/
public function testIpv6CIDRcheck()
{
// check CIDR w/o mask
$this->assertFalse(Net::ipCIDRcheck('2001:0DB8::', '2001:0DB8::1'));
// check wrong CIDR w/ mask
$this->assertFalse(Net::ipCIDRcheck('2001:0DB8::/128', '2001:0DB8::1'));
// check wrong IP
$this->assertFalse(Net::ipCIDRcheck('2001:0DB8::/128', '2001:0DB8::Z'));
// check limits for standard classes
$this->assertTrue(Net::ipCIDRcheck('2001:0DB8::/128', '2001:0DB8:0000:0000:0000:0000:0000:0000'));
$this->assertTrue(Net::ipCIDRcheck('2001:0DB8::/128', '2001:0DB8::0'));
$this->assertFalse(Net::ipCIDRcheck('2001:0DB8::/128', '2001:0DB8::1'));
$this->assertTrue(Net::ipCIDRcheck('2001:0DB8::/112', '2001:0DB8::1'));
$this->assertFalse(Net::ipCIDRcheck('2001:0DB8::/112', '2001:0DB8::1:1'));
$this->assertTrue(Net::ipCIDRcheck('2001:0DB8::/112', '2001:0DB8::FFFF'));
$this->assertFalse(Net::ipCIDRcheck('2001:0DB8::/112', '2001:0DB8::1:FFFF'));
// check limits for non-standard classes
$this->assertTrue(Net::ipCIDRcheck('2001:0DB8::/108', '2001:0DB8::1:1'));
$this->assertTrue(Net::ipCIDRcheck('2001:0DB8::/108', '2001:0DB8::F:1'));
$this->assertFalse(Net::ipCIDRcheck('2001:0DB8::/108', '2001:0DB8::FF:1'));
$this->assertFalse(Net::ipCIDRcheck('2001:0DB8::/108', '2001:0DB8::1FF:1'));
$this->assertFalse(Net::ipCIDRcheck('2001:0DB8::/108', '2001:0DB8::FFFF:1'));
$this->assertTrue(Net::ipCIDRcheck('2001:0DB8::/104', '2001:0DB8::1:1'));
$this->assertTrue(Net::ipCIDRcheck('2001:0DB8::/104', '2001:0DB8::F:1'));
$this->assertTrue(Net::ipCIDRcheck('2001:0DB8::/104', '2001:0DB8::FF:1'));
$this->assertFalse(Net::ipCIDRcheck('2001:0DB8::/104', '2001:0DB8::1FF:1'));
$this->assertFalse(Net::ipCIDRcheck('2001:0DB8::/104', '2001:0DB8::FFFF:1'));
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Utils/ArraysTest.php 0000644 0000000 0000000 00000007015 13245225037 022713 0 ustar root root assertEquals($array, Arrays::arrayize($array));
// check non-empty array as input
$array = array('key' => 'value');
$this->assertEquals($array, Arrays::arrayize($array));
// check indexes are ignored when input is an array
$this->assertArrayNotHasKey('invalid', Arrays::arrayize($array, 'invalid'));
// check default index
$expected = array('string');
$this->assertEquals($expected, Arrays::arrayize($expected[0]));
// check string index
$index = 'key';
$expected = array($index => 'string');
$this->assertEquals($expected, Arrays::arrayize($expected[$index], $index));
}
/**
* Test the transpose() function.
*/
public function testTranspose()
{
// check not array
$this->assertFalse(Arrays::transpose('string'));
// check bad arrays
$this->assertFalse(
Arrays::transpose(array('1', '2', '3')),
'Invalid two-dimensional array was accepted'
);
$this->assertFalse(
Arrays::transpose(array('1' => 0, '2' => '0', '3' => array(0))),
'Invalid elements on a two-dimensional array were accepted'
);
// check array with numerical keys
$array = array(
'key1' => array(
'value1'
),
'key2' => array(
'value1',
'value2'
)
);
$transposed = array(
array(
'key1' => 'value1',
'key2' => 'value1'
),
array(
'key2' => 'value2'
)
);
$this->assertEquals(
$transposed,
Arrays::transpose($array),
'Unexpected result of transpose()'
);
// check array with string keys
$array = array(
'key1' => array(
'subkey1' => 'value1'
),
'key2' => array(
'subkey1' => 'value1',
'subkey2' => 'value2'
)
);
$transposed = array(
'subkey1' => array(
'key1' => 'value1',
'key2' => 'value1'
),
'subkey2' => array(
'key2' => 'value2'
)
);
$this->assertEquals(
$transposed,
Arrays::transpose($array),
'Unexpected result of transpose()'
);
// check array with no keys in common between sub arrays
$array = array(
'key1' => array(
'subkey1' => 'value1'
),
'key2' => array(
'subkey2' => 'value1',
'subkey3' => 'value2'
)
);
$transposed = array(
'subkey1' => array(
'key1' => 'value1',
),
'subkey2' => array(
'key2' => 'value1'
),
'subkey3' => array(
'key2' => 'value2'
)
);
$this->assertEquals(
$transposed,
Arrays::transpose($array),
'Unexpected result of transpose()'
);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Utils/HTTPTest.php 0000644 0000000 0000000 00000035231 13245225037 022232 0 ustar root root 'bar',
'bar' => 'foo',
);
$this->assertEquals($url.'?foo=bar&bar=foo', HTTP::addURLParameters($url, $params));
$url = 'http://example.com/?';
$params = array(
'foo' => 'bar',
'bar' => 'foo',
);
$this->assertEquals($url.'foo=bar&bar=foo', HTTP::addURLParameters($url, $params));
$url = 'http://example.com/?foo=bar';
$params = array(
'bar' => 'foo',
);
$this->assertEquals($url.'&bar=foo', HTTP::addURLParameters($url, $params));
}
/**
* Test SimpleSAML\Utils\HTTP::guessBasePath().
*/
public function testGuessBasePath()
{
$original = $_SERVER;
$_SERVER['REQUEST_URI'] = '/simplesaml/module.php';
$_SERVER['SCRIPT_FILENAME'] = '/some/path/simplesamlphp/www/module.php';
$this->assertEquals('/simplesaml/', HTTP::guessBasePath());
$_SERVER['REQUEST_URI'] = '/simplesaml/module.php/some/path/to/other/script.php';
$_SERVER['SCRIPT_FILENAME'] = '/some/path/simplesamlphp/www/module.php';
$this->assertEquals('/simplesaml/', HTTP::guessBasePath());
$_SERVER['REQUEST_URI'] = '/module.php';
$_SERVER['SCRIPT_FILENAME'] = '/some/path/simplesamlphp/www/module.php';
$this->assertEquals('/', HTTP::guessBasePath());
$_SERVER['REQUEST_URI'] = '/module.php/some/path/to/other/script.php';
$_SERVER['SCRIPT_FILENAME'] = '/some/path/simplesamlphp/www/module.php';
$this->assertEquals('/', HTTP::guessBasePath());
$_SERVER['REQUEST_URI'] = '/some/path/module.php';
$_SERVER['SCRIPT_FILENAME'] = '/some/path/simplesamlphp/www/module.php';
$this->assertEquals('/some/path/', HTTP::guessBasePath());
$_SERVER['REQUEST_URI'] = '/some/path/module.php/some/path/to/other/script.php';
$_SERVER['SCRIPT_FILENAME'] = '/some/path/simplesamlphp/www/module.php';
$this->assertEquals('/some/path/', HTTP::guessBasePath());
$_SERVER['REQUEST_URI'] = '/some/dir/in/www/script.php';
$_SERVER['SCRIPT_FILENAME'] = '/some/path/simplesamlphp/www/some/dir/in/www/script.php';
$this->assertEquals('/', HTTP::guessBasePath());
$_SERVER['REQUEST_URI'] = '/simplesaml/some/dir/in/www/script.php';
$_SERVER['SCRIPT_FILENAME'] = '/some/path/simplesamlphp/www/some/dir/in/www/script.php';
$this->assertEquals('/simplesaml/', HTTP::guessBasePath());
$_SERVER = $original;
}
/**
* Test SimpleSAML\Utils\HTTP::getSelfHost() with and without custom port.
*/
public function testGetSelfHost()
{
$original = $_SERVER;
\SimpleSAML_Configuration::loadFromArray(array(
'baseurlpath' => '',
), '[ARRAY]', 'simplesaml');
$_SERVER['SERVER_PORT'] = '80';
$this->assertEquals('localhost', HTTP::getSelfHost());
$_SERVER['SERVER_PORT'] = '3030';
$this->assertEquals('localhost', HTTP::getSelfHost());
$_SERVER = $original;
}
/**
* Test SimpleSAML\Utils\HTTP::getSelfHostWithPort(), with and without custom port.
*/
public function testGetSelfHostWithPort()
{
$original = $_SERVER;
\SimpleSAML_Configuration::loadFromArray(array(
'baseurlpath' => '',
), '[ARRAY]', 'simplesaml');
// standard port for HTTP
$_SERVER['SERVER_PORT'] = '80';
$this->assertEquals('localhost', HTTP::getSelfHostWithNonStandardPort());
// non-standard port
$_SERVER['SERVER_PORT'] = '3030';
$this->assertEquals('localhost:3030', HTTP::getSelfHostWithNonStandardPort());
// standard port for HTTPS
$_SERVER['HTTPS'] = 'on';
$_SERVER['SERVER_PORT'] = '443';
$this->assertEquals('localhost', HTTP::getSelfHostWithNonStandardPort());
$_SERVER = $original;
}
/**
* Test SimpleSAML\Utils\HTTP::getSelfURL().
*/
public function testGetSelfURLMethods()
{
$original = $_SERVER;
/*
* Test a URL pointing to a script that's not part of the public interface. This allows us to test calls to
* getSelfURL() from scripts outside of SimpleSAMLphp
*/
\SimpleSAML_Configuration::loadFromArray(array(
'baseurlpath' => 'http://example.com/simplesaml/',
), '[ARRAY]', 'simplesaml');
$url = 'https://example.com/app/script.php/some/path?foo=bar';
$this->setupEnvFromURL($url);
$_SERVER['SCRIPT_FILENAME'] = '/var/www/app/script.php';
$this->assertEquals($url, HTTP::getSelfURL());
$this->assertEquals('https://example.com', HTTP::getSelfURLHost());
$this->assertEquals('https://example.com/app/script.php/some/path', HTTP::getSelfURLNoQuery());
$this->assertTrue(HTTP::isHTTPS());
$this->assertEquals('https://'.HTTP::getSelfHostWithNonStandardPort(), HTTP::getSelfURLHost());
// test a request URI that doesn't match the current script
$cfg = \SimpleSAML_Configuration::loadFromArray(array(
'baseurlpath' => 'https://example.org/simplesaml/',
), '[ARRAY]', 'simplesaml');
$baseDir = $cfg->getBaseDir();
$_SERVER['SCRIPT_FILENAME'] = $baseDir.'www/module.php';
$this->setupEnvFromURL('http://www.example.com/protected/resource.asp?foo=bar');
$this->assertEquals('http://www.example.com/protected/resource.asp?foo=bar', HTTP::getSelfURL());
$this->assertEquals('http://www.example.com', HTTP::getSelfURLHost());
$this->assertEquals('http://www.example.com/protected/resource.asp', HTTP::getSelfURLNoQuery());
$this->assertFalse(HTTP::isHTTPS());
$this->assertEquals('example.org', HTTP::getSelfHostWithNonStandardPort());
$this->assertEquals('http://www.example.com', HTTP::getSelfURLHost());
// test a valid, full URL, based on a full URL in the configuration
\SimpleSAML_Configuration::loadFromArray(array(
'baseurlpath' => 'https://example.com/simplesaml/',
), '[ARRAY]', 'simplesaml');
$this->setupEnvFromURL('http://www.example.org/module.php/module/file.php?foo=bar');
$this->assertEquals(
'https://example.com/simplesaml/module.php/module/file.php?foo=bar',
HTTP::getSelfURL()
);
$this->assertEquals('https://example.com', HTTP::getSelfURLHost());
$this->assertEquals('https://example.com/simplesaml/module.php/module/file.php', HTTP::getSelfURLNoQuery());
$this->assertTrue(HTTP::isHTTPS());
$this->assertEquals('https://'.HTTP::getSelfHostWithNonStandardPort(), HTTP::getSelfURLHost());
// test a valid, full URL, based on a full URL *without* a trailing slash in the configuration
\SimpleSAML_Configuration::loadFromArray(array(
'baseurlpath' => 'https://example.com/simplesaml',
), '[ARRAY]', 'simplesaml');
$this->assertEquals(
'https://example.com/simplesaml/module.php/module/file.php?foo=bar',
HTTP::getSelfURL()
);
$this->assertEquals('https://example.com', HTTP::getSelfURLHost());
$this->assertEquals('https://example.com/simplesaml/module.php/module/file.php', HTTP::getSelfURLNoQuery());
$this->assertTrue(HTTP::isHTTPS());
$this->assertEquals('https://'.HTTP::getSelfHostWithNonStandardPort(), HTTP::getSelfURLHost());
// test a valid, full URL, based on a full URL *without* a path in the configuration
\SimpleSAML_Configuration::loadFromArray(array(
'baseurlpath' => 'https://example.com',
), '[ARRAY]', 'simplesaml');
$this->assertEquals(
'https://example.com/module.php/module/file.php?foo=bar',
HTTP::getSelfURL()
);
$this->assertEquals('https://example.com', HTTP::getSelfURLHost());
$this->assertEquals('https://example.com/module.php/module/file.php', HTTP::getSelfURLNoQuery());
$this->assertTrue(HTTP::isHTTPS());
$this->assertEquals('https://'.HTTP::getSelfHostWithNonStandardPort(), HTTP::getSelfURLHost());
// test a valid, full URL, based on a relative path in the configuration
\SimpleSAML_Configuration::loadFromArray(array(
'baseurlpath' => '/simplesaml/',
), '[ARRAY]', 'simplesaml');
$this->setupEnvFromURL('http://www.example.org/simplesaml/module.php/module/file.php?foo=bar');
$this->assertEquals(
'http://www.example.org/simplesaml/module.php/module/file.php?foo=bar',
HTTP::getSelfURL()
);
$this->assertEquals('http://www.example.org', HTTP::getSelfURLHost());
$this->assertEquals('http://www.example.org/simplesaml/module.php/module/file.php', HTTP::getSelfURLNoQuery());
$this->assertFalse(HTTP::isHTTPS());
$this->assertEquals('http://'.HTTP::getSelfHostWithNonStandardPort(), HTTP::getSelfURLHost());
// test a valid, full URL, based on a relative path in the configuration and a non standard port
\SimpleSAML_Configuration::loadFromArray(array(
'baseurlpath' => '/simplesaml/',
), '[ARRAY]', 'simplesaml');
$this->setupEnvFromURL('http://example.org:8080/simplesaml/module.php/module/file.php?foo=bar');
$this->assertEquals(
'http://example.org:8080/simplesaml/module.php/module/file.php?foo=bar',
HTTP::getSelfURL()
);
$this->assertEquals('http://example.org:8080', HTTP::getSelfURLHost());
$this->assertEquals('http://example.org:8080/simplesaml/module.php/module/file.php', HTTP::getSelfURLNoQuery());
$this->assertFalse(HTTP::isHTTPS());
$this->assertEquals('http://'.HTTP::getSelfHostWithNonStandardPort(), HTTP::getSelfURLHost());
// test a valid, full URL, based on a relative path in the configuration, a non standard port and HTTPS
\SimpleSAML_Configuration::loadFromArray(array(
'baseurlpath' => '/simplesaml/',
), '[ARRAY]', 'simplesaml');
$this->setupEnvFromURL('https://example.org:8080/simplesaml/module.php/module/file.php?foo=bar');
$this->assertEquals(
'https://example.org:8080/simplesaml/module.php/module/file.php?foo=bar',
HTTP::getSelfURL()
);
$this->assertEquals('https://example.org:8080', HTTP::getSelfURLHost());
$this->assertEquals(
'https://example.org:8080/simplesaml/module.php/module/file.php',
HTTP::getSelfURLNoQuery()
);
$this->assertTrue(HTTP::isHTTPS());
$this->assertEquals('https://'.HTTP::getSelfHostWithNonStandardPort(), HTTP::getSelfURLHost());
$_SERVER = $original;
}
/**
* Test SimpleSAML\Utils\HTTP::checkURLAllowed(), without regex.
*/
public function testCheckURLAllowedWithoutRegex()
{
$original = $_SERVER;
\SimpleSAML_Configuration::loadFromArray(array(
'trusted.url.domains' => array('sp.example.com', 'app.example.com'),
'trusted.url.regex' => false,
), '[ARRAY]', 'simplesaml');
$_SERVER['REQUEST_URI'] = '/module.php';
$allowed = array(
'https://sp.example.com/',
'http://sp.example.com/',
'https://app.example.com/',
'http://app.example.com/',
);
foreach ($allowed as $url) {
$this->assertEquals(HTTP::checkURLAllowed($url), $url);
}
$this->setExpectedException('SimpleSAML_Error_Exception');
HTTP::checkURLAllowed('https://evil.com');
$_SERVER = $original;
}
/**
* Test SimpleSAML\Utils\HTTP::checkURLAllowed(), with regex.
*/
public function testCheckURLAllowedWithRegex()
{
$original = $_SERVER;
\SimpleSAML_Configuration::loadFromArray(array(
'trusted.url.domains' => array('.*\.example\.com'),
'trusted.url.regex' => true,
), '[ARRAY]', 'simplesaml');
$_SERVER['REQUEST_URI'] = '/module.php';
$allowed = array(
'https://sp.example.com/',
'http://sp.example.com/',
'https://app1.example.com/',
'http://app1.example.com/',
'https://app2.example.com/',
'http://app2.example.com/',
);
foreach ($allowed as $url) {
$this->assertEquals(HTTP::checkURLAllowed($url), $url);
}
$this->setExpectedException('SimpleSAML_Error_Exception');
HTTP::checkURLAllowed('https://evil.com');
$_SERVER = $original;
}
/**
* Test SimpleSAML\Utils\HTTP::checkURLAllowed(), with the regex as a
* subdomain of an evil domain.
*/
public function testCheckURLAllowedWithRegexWithoutDelimiters()
{
$original = $_SERVER;
\SimpleSAML_Configuration::loadFromArray(array(
'trusted.url.domains' => array('app\.example\.com'),
'trusted.url.regex' => true,
), '[ARRAY]', 'simplesaml');
$_SERVER['REQUEST_URI'] = '/module.php';
$this->setExpectedException('SimpleSAML_Error_Exception');
HTTP::checkURLAllowed('https://app.example.com.evil.com');
$_SERVER = $original;
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Utils/ConfigTest.php 0000644 0000000 0000000 00000002710 13245225037 022654 0 ustar root root assertEquals($configDir, dirname(dirname(dirname(dirname(__DIR__)))) . '/config');
}
/**
* Test valid dir specified by env var overrides default config dir
*/
public function testEnvVariableConfigDir()
{
putenv('SIMPLESAMLPHP_CONFIG_DIR=' . __DIR__);
$configDir = Config::getConfigDir();
$this->assertEquals($configDir, __DIR__);
}
/**
* Test invalid dir specified by env var results in a thrown exception
*/
public function testInvalidEnvVariableConfigDirThrowsException()
{
// I used a random hash to ensure this test directory is always invalid
$invalidDir = __DIR__ . '/e9826ad19cbc4f5bf20c0913ffcd2ce6';
putenv('SIMPLESAMLPHP_CONFIG_DIR=' . $invalidDir);
$this->setExpectedException(
'InvalidArgumentException',
'Config directory specified by environment variable SIMPLESAMLPHP_CONFIG_DIR is not a directory. ' .
'Given: "' . $invalidDir . '"'
);
Config::getConfigDir();
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Utils/Config/ 0000755 0000000 0000000 00000000000 13245225037 021303 5 ustar root root simplesamlphp-1.15.3/tests/lib/SimpleSAML/Utils/Config/MetadataTest.php 0000644 0000000 0000000 00000022410 13245225037 024373 0 ustar root root assertEquals('Invalid input parameters', $e->getMessage());
}
// test missing type
$contact = array(
'name' => 'John Doe'
);
try {
Metadata::getContact($contact);
} catch (\InvalidArgumentException $e) {
$this->assertStringStartsWith('"contactType" is mandatory and must be one of ', $e->getMessage());
}
// test invalid type
$contact = array(
'contactType' => 'invalid'
);
try {
Metadata::getContact($contact);
} catch (\InvalidArgumentException $e) {
$this->assertStringStartsWith('"contactType" is mandatory and must be one of ', $e->getMessage());
}
// test all valid contact types
foreach (Metadata::$VALID_CONTACT_TYPES as $type) {
$contact = array(
'contactType' => $type
);
$parsed = Metadata::getContact($contact);
$this->assertArrayHasKey('contactType', $parsed);
$this->assertArrayNotHasKey('givenName', $parsed);
$this->assertArrayNotHasKey('surName', $parsed);
}
// test basic name parsing
$contact = array(
'contactType' => 'technical',
'name' => 'John Doe'
);
$parsed = Metadata::getContact($contact);
$this->assertArrayNotHasKey('name', $parsed);
$this->assertArrayHasKey('givenName', $parsed);
$this->assertArrayHasKey('surName', $parsed);
$this->assertEquals('John', $parsed['givenName']);
$this->assertEquals('Doe', $parsed['surName']);
// test comma-separated names
$contact = array(
'contactType' => 'technical',
'name' => 'Doe, John'
);
$parsed = Metadata::getContact($contact);
$this->assertArrayHasKey('givenName', $parsed);
$this->assertArrayHasKey('surName', $parsed);
$this->assertEquals('John', $parsed['givenName']);
$this->assertEquals('Doe', $parsed['surName']);
// test long names
$contact = array(
'contactType' => 'technical',
'name' => 'John Fitzgerald Doe Smith'
);
$parsed = Metadata::getContact($contact);
$this->assertArrayNotHasKey('name', $parsed);
$this->assertArrayHasKey('givenName', $parsed);
$this->assertArrayNotHasKey('surName', $parsed);
$this->assertEquals('John Fitzgerald Doe Smith', $parsed['givenName']);
// test comma-separated long names
$contact = array(
'contactType' => 'technical',
'name' => 'Doe Smith, John Fitzgerald'
);
$parsed = Metadata::getContact($contact);
$this->assertArrayNotHasKey('name', $parsed);
$this->assertArrayHasKey('givenName', $parsed);
$this->assertArrayHasKey('surName', $parsed);
$this->assertEquals('John Fitzgerald', $parsed['givenName']);
$this->assertEquals('Doe Smith', $parsed['surName']);
// test givenName
$contact = array(
'contactType' => 'technical',
);
$invalid_types = array(0, array(0), 0.1, true, false);
foreach ($invalid_types as $type) {
$contact['givenName'] = $type;
try {
Metadata::getContact($contact);
} catch (\InvalidArgumentException $e) {
$this->assertEquals('"givenName" must be a string and cannot be empty.', $e->getMessage());
}
}
// test surName
$contact = array(
'contactType' => 'technical',
);
$invalid_types = array(0, array(0), 0.1, true, false);
foreach ($invalid_types as $type) {
$contact['surName'] = $type;
try {
Metadata::getContact($contact);
} catch (\InvalidArgumentException $e) {
$this->assertEquals('"surName" must be a string and cannot be empty.', $e->getMessage());
}
}
// test company
$contact = array(
'contactType' => 'technical',
);
$invalid_types = array(0, array(0), 0.1, true, false);
foreach ($invalid_types as $type) {
$contact['company'] = $type;
try {
Metadata::getContact($contact);
} catch (\InvalidArgumentException $e) {
$this->assertEquals('"company" must be a string and cannot be empty.', $e->getMessage());
}
}
// test emailAddress
$contact = array(
'contactType' => 'technical',
);
$invalid_types = array(0, 0.1, true, false, array());
foreach ($invalid_types as $type) {
$contact['emailAddress'] = $type;
try {
Metadata::getContact($contact);
} catch (\InvalidArgumentException $e) {
$this->assertEquals(
'"emailAddress" must be a string or an array and cannot be empty.',
$e->getMessage()
);
}
}
$invalid_types = array(array("string", true), array("string", 0));
foreach ($invalid_types as $type) {
$contact['emailAddress'] = $type;
try {
Metadata::getContact($contact);
} catch (\InvalidArgumentException $e) {
$this->assertEquals(
'Email addresses must be a string and cannot be empty.',
$e->getMessage()
);
}
}
$valid_types = array('email@example.com', array('email1@example.com', 'email2@example.com'));
foreach ($valid_types as $type) {
$contact['emailAddress'] = $type;
$parsed = Metadata::getContact($contact);
$this->assertEquals($type, $parsed['emailAddress']);
}
// test telephoneNumber
$contact = array(
'contactType' => 'technical',
);
$invalid_types = array(0, 0.1, true, false, array());
foreach ($invalid_types as $type) {
$contact['telephoneNumber'] = $type;
try {
Metadata::getContact($contact);
} catch (\InvalidArgumentException $e) {
$this->assertEquals(
'"telephoneNumber" must be a string or an array and cannot be empty.',
$e->getMessage()
);
}
}
$invalid_types = array(array("string", true), array("string", 0));
foreach ($invalid_types as $type) {
$contact['telephoneNumber'] = $type;
try {
Metadata::getContact($contact);
} catch (\InvalidArgumentException $e) {
$this->assertEquals('Telephone numbers must be a string and cannot be empty.', $e->getMessage());
}
}
$valid_types = array('1234', array('1234', '5678'));
foreach ($valid_types as $type) {
$contact['telephoneNumber'] = $type;
$parsed = Metadata::getContact($contact);
$this->assertEquals($type, $parsed['telephoneNumber']);
}
// test completeness
$contact = array();
foreach (Metadata::$VALID_CONTACT_OPTIONS as $option) {
$contact[$option] = 'string';
}
$contact['contactType'] = 'technical';
$contact['name'] = 'to_be_removed';
$contact['attributes'] = array('test' => 'testval');
$parsed = Metadata::getContact($contact);
foreach (array_keys($parsed) as $key) {
$this->assertEquals($parsed[$key], $contact[$key]);
}
$this->assertArrayNotHasKey('name', $parsed);
}
/**
* Test \SimpleSAML\Utils\Config\Metadata::isHiddenFromDiscovery().
*/
public function testIsHiddenFromDiscovery()
{
// test for success
$metadata = array(
'EntityAttributes' => array(
Metadata::$ENTITY_CATEGORY => array(
Metadata::$HIDE_FROM_DISCOVERY,
),
),
);
$this->assertTrue(Metadata::isHiddenFromDiscovery($metadata));
// test for failures
$this->assertFalse(Metadata::isHiddenFromDiscovery(array('foo')));
$this->assertFalse(Metadata::isHiddenFromDiscovery(array(
'EntityAttributes' => 'bar',
)));
$this->assertFalse(Metadata::isHiddenFromDiscovery(array(
'EntityAttributes' => array(),
)));
$this->assertFalse(Metadata::isHiddenFromDiscovery(array(
'EntityAttributes' => array(
Metadata::$ENTITY_CATEGORY => '',
),
)));
$this->assertFalse(Metadata::isHiddenFromDiscovery(array(
'EntityAttributes' => array(
Metadata::$ENTITY_CATEGORY => array(),
),
)));
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Utils/CryptoTest.php 0000644 0000000 0000000 00000037221 13245225037 022734 0 ustar root root root = vfsStream::setup(
self::ROOTDIRNAME,
null,
array(
self::DEFAULTCERTDIR => array(),
)
);
$this->root_directory = vfsStream::url(self::ROOTDIRNAME);
$this->certdir = $this->root_directory.DIRECTORY_SEPARATOR.self::DEFAULTCERTDIR;
}
/**
* Test invalid input provided to the aesDecrypt() method.
*
* @expectedException \InvalidArgumentException
*
* @covers \SimpleSAML\Utils\Crypto::_aesDecrypt
*/
public function testAesDecryptBadInput()
{
$m = new \ReflectionMethod('\SimpleSAML\Utils\Crypto', '_aesDecrypt');
$m->setAccessible(true);
$m->invokeArgs(null, array(array(), 'SECRET'));
}
/**
* Test invalid input provided to the aesEncrypt() method.
*
* @expectedException \InvalidArgumentException
*
* @covers \SimpleSAML\Utils\Crypto::_aesEncrypt
*/
public function testAesEncryptBadInput()
{
$m = new \ReflectionMethod('\SimpleSAML\Utils\Crypto', '_aesEncrypt');
$m->setAccessible(true);
$m->invokeArgs(null, array(array(), 'SECRET'));
}
/**
* Test that aesDecrypt() works properly, being able to decrypt some previously known (and correct)
* ciphertext.
*
* @covers \SimpleSAML\Utils\Crypto::_aesDecrypt
*/
public function testAesDecrypt()
{
if (!extension_loaded('openssl')) {
$this->setExpectedException('\SimpleSAML_Error_Exception');
}
$secret = 'SUPER_SECRET_SALT';
$m = new \ReflectionMethod('\SimpleSAML\Utils\Crypto', '_aesDecrypt');
$m->setAccessible(true);
$plaintext = 'SUPER_SECRET_TEXT';
$ciphertext = 'uR2Yu0r4itInKx91D/l9y/08L5CIQyev9nAr27fh3Sshous4vbXRRcMcjqHDOrquD+2vqLyw7ygnbA9jA9TpB4hLZocvAWcTN8tyO82hiSY=';
$this->assertEquals($plaintext, $m->invokeArgs(null, array(base64_decode($ciphertext), $secret)));
}
/**
* Test that aesEncrypt() produces ciphertexts that aesDecrypt() can decrypt.
*
* @covers \SimpleSAML\Utils\Crypto::_aesDecrypt
* @covers \SimpleSAML\Utils\Crypto::_aesEncrypt
*/
public function testAesEncrypt()
{
if (!extension_loaded('openssl')) {
$this->setExpectedException('\SimpleSAML_Error_Exception');
}
$secret = 'SUPER_SECRET_SALT';
$e = new \ReflectionMethod('\SimpleSAML\Utils\Crypto', '_aesEncrypt');
$d = new \ReflectionMethod('\SimpleSAML\Utils\Crypto', '_aesDecrypt');
$e->setAccessible(true);
$d->setAccessible(true);
$original_plaintext = 'SUPER_SECRET_TEXT';
$ciphertext = $e->invokeArgs(null, array($original_plaintext, $secret));
$decrypted_plaintext = $d->invokeArgs(null, array($ciphertext, $secret));
$this->assertEquals($original_plaintext, $decrypted_plaintext);
}
/**
* Test that the pem2der() and der2pem() methods work correctly.
*
* @covers \SimpleSAML\Utils\Crypto::der2pem
* @covers \SimpleSAML\Utils\Crypto::pem2der
*/
public function testFormatConversion()
{
$pem = <<assertEquals(trim($pem), trim(Crypto::der2pem(Crypto::pem2der($pem))));
}
/**
* @covers \SimpleSAML\Utils\Crypto::pwHash
*/
public function testGoodPwHash()
{
$pw = "password";
$algorithm = "SHA1";
$res = Crypto::pwHash($pw, $algorithm);
/*
* echo -n "password" | sha1sum | awk -F " " '{print $1}' | xxd -r -p | base64
* W6ph5Mm5Pz8GgiULbPgzG37mj9g=
*/
$expected = "{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=";
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\Crypto::pwHash
*/
public function testGoodSaltedPwHash()
{
$pw = "password";
$algorithm = "SSHA1";
$salt = "salt";
$res = Crypto::pwHash($pw, $algorithm, $salt);
/*
* echo -n "password""salt" | sha1sum | awk -v salt=$(echo -n "salt" | xxd -u -p) -F " " '{print $1 salt}' | xxd -r -p | base64
* yI6cZwQadOA1e+/f+T+H3eCQQhRzYWx0
*/
$expected = "{SSHA}yI6cZwQadOA1e+/f+T+H3eCQQhRzYWx0";
$this->assertEquals($expected, $res);
}
/**
* @expectedException \SimpleSAML_Error_Exception
*
* @covers \SimpleSAML\Utils\Crypto::pwHash
*/
public function testBadHashAlgorithm()
{
$pw = "password";
$algorithm = "wtf";
Crypto::pwHash($pw, $algorithm);
}
/**
* @covers \SimpleSAML\Utils\Crypto::pwValid
*/
public function testGoodPwValid()
{
$pw = "password";
$algorithm = "SHA1";
$hash = Crypto::pwHash($pw, $algorithm);
$res = Crypto::pwValid($hash, $pw);
$this->assertTrue($res);
}
/**
* @covers \SimpleSAML\Utils\Crypto::pwValid
*/
public function testGoodSaltedPwValid()
{
$pw = "password";
$algorithm = "SSHA1";
$salt = "salt";
$hash = Crypto::pwHash($pw, $algorithm, $salt);
$res = Crypto::pwValid($hash, $pw);
$this->assertTrue($res);
}
/**
* @expectedException \SimpleSAML_Error_Exception
*
* @covers \SimpleSAML\Utils\Crypto::pwValid
*/
public function testBadHashAlgorithmValid()
{
$pw = "password";
$algorithm = "wtf";
$hash = "{".$algorithm."}B64STRING";
Crypto::pwValid($hash, $algorithm);
}
/**
* @covers \SimpleSAML\Utils\Crypto::secureCompare
*/
public function testSecureCompareEqual()
{
$res = Crypto::secureCompare("string", "string");
$this->assertTrue($res);
}
/**
* @covers \SimpleSAML\Utils\Crypto::secureCompare
*/
public function testSecureCompareNotEqual()
{
$res = Crypto::secureCompare("string1", "string2");
$this->assertFalse($res);
}
/**
* @expectedException \SimpleSAML_Error_Exception
*
* @covers \SimpleSAML\Utils\Crypto::loadPrivateKey
*/
public function testLoadPrivateKeyRequiredMetadataMissing()
{
$config = new Configuration(array(), 'test');
$required = true;
Crypto::loadPrivateKey($config, $required);
}
/**
* @covers \SimpleSAML\Utils\Crypto::loadPrivateKey
*/
public function testLoadPrivateKeyNotRequiredMetadataMissing()
{
$config = new Configuration(array(), 'test');
$required = false;
$res = Crypto::loadPrivateKey($config, $required);
$this->assertNull($res);
}
/**
* @expectedException \SimpleSAML_Error_Exception
*
* @covers \SimpleSAML\Utils\Crypto::loadPrivateKey
*/
public function testLoadPrivateKeyMissingFile()
{
$config = new Configuration(array('privatekey' => 'nonexistant'), 'test');
Crypto::loadPrivateKey($config, false, '', true);
}
/**
* @covers \SimpleSAML\Utils\Crypto::loadPrivateKey
*/
public function testLoadPrivateKeyBasic()
{
$filename = $this->certdir.DIRECTORY_SEPARATOR.'key';
$data = 'data';
$config = new Configuration(array('privatekey' => $filename), 'test');
$full_path = true;
file_put_contents($filename, $data);
$res = Crypto::loadPrivateKey($config, false, '', $full_path);
$expected = array('PEM' => $data);
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\Crypto::loadPrivateKey
*/
public function testLoadPrivateKeyPassword()
{
$password = 'password';
$filename = $this->certdir.DIRECTORY_SEPARATOR.'key';
$data = 'data';
$config = new Configuration(
array(
'privatekey' => $filename,
'privatekey_pass' => $password,
),
'test'
);
$full_path = true;
file_put_contents($filename, $data);
$res = Crypto::loadPrivateKey($config, false, '', $full_path);
$expected = array('PEM' => $data, 'password' => $password);
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\Crypto::loadPrivateKey
*/
public function testLoadPrivateKeyPrefix()
{
$prefix = 'prefix';
$password = 'password';
$filename = $this->certdir.DIRECTORY_SEPARATOR.'key';
$data = 'data';
$config = new Configuration(
array(
$prefix.'privatekey' => $filename,
$prefix.'privatekey_pass' => $password,
),
'test'
);
$full_path = true;
file_put_contents($filename, $data);
$res = Crypto::loadPrivateKey($config, false, $prefix, $full_path);
$expected = array('PEM' => $data, 'password' => $password);
$this->assertEquals($expected, $res);
}
/**
* @expectedException \SimpleSAML_Error_Exception
*
* @covers \SimpleSAML\Utils\Crypto::loadPublicKey
*/
public function testLoadPublicKeyRequiredMetadataMissing()
{
$config = new Configuration(array(), 'test');
$required = true;
Crypto::loadPublicKey($config, $required);
}
/**
* @covers \SimpleSAML\Utils\Crypto::loadPublicKey
*/
public function testLoadPublicKeyNotRequiredMetadataMissing()
{
$config = new Configuration(array(), 'test');
$required = false;
$res = Crypto::loadPublicKey($config, $required);
$this->assertNull($res);
}
/**
* @covers \SimpleSAML\Utils\Crypto::loadPublicKey
*/
public function testLoadPublicKeyFingerprintBasicString()
{
$fingerprint = 'fingerprint';
$config = new Configuration(array('certFingerprint' => $fingerprint), 'test');
$res = Crypto::loadPublicKey($config);
$expected = array('certFingerprint' => array($fingerprint));
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\Crypto::loadPublicKey
*/
public function testLoadPublicKeyFingerprintBasicArray()
{
$fingerprint1 = 'fingerprint1';
$fingerprint2 = 'fingerprint2';
$config = new Configuration(
array(
'certFingerprint' => array(
$fingerprint1,
$fingerprint2
),
),
'test'
);
$res = Crypto::loadPublicKey($config);
$expected = array('certFingerprint' => array($fingerprint1, $fingerprint2));
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\Crypto::loadPublicKey
*/
public function testLoadPublicKeyFingerprintLowercase()
{
$fingerprint = 'FINGERPRINT';
$config = new Configuration(array('certFingerprint' => $fingerprint), 'test');
$res = Crypto::loadPublicKey($config);
$expected = array('certFingerprint' => array(strtolower($fingerprint)));
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\Crypto::loadPublicKey
*/
public function testLoadPublicKeyFingerprintRemoveColons()
{
$fingerprint = 'f:i:n:g:e:r:p:r:i:n:t';
$config = new Configuration(array('certFingerprint' => $fingerprint), 'test');
$res = Crypto::loadPublicKey($config);
$expected = array('certFingerprint' => array(str_replace(':', '', $fingerprint)));
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\Crypto::loadPublicKey
*/
public function testLoadPublicKeyNotX509Certificate()
{
$config = new Configuration(
array(
'keys' => array(
array(
'X509Certificate' => '',
'type' => 'NotX509Certificate',
'signing' => true
),
),
),
'test'
);
$res = Crypto::loadPublicKey($config);
$this->assertNull($res);
}
/**
* @covers \SimpleSAML\Utils\Crypto::loadPublicKey
*/
public function testLoadPublicKeyNotSigning()
{
$config = new Configuration(
array(
'keys' => array(
array(
'X509Certificate' => '',
'type' => 'X509Certificate',
'signing' => false
),
),
),
'test'
);
$res = Crypto::loadPublicKey($config);
$this->assertNull($res);
}
/**
* @covers \SimpleSAML\Utils\Crypto::loadPublicKey
*/
public function testLoadPublicKeyBasic()
{
$x509certificate = 'x509certificate';
$config = new Configuration(
array(
'keys' => array(
array(
'X509Certificate' => $x509certificate,
'type' => 'X509Certificate',
'signing' => true
),
),
),
'test'
);
$pubkey = Crypto::loadPublicKey($config);
$res = $pubkey['certData'];
$expected = $x509certificate;
$this->assertEquals($expected, $res);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Utils/SystemTest.php 0000644 0000000 0000000 00000014457 13245225037 022746 0 ustar root root root = vfsStream::setup(
self::ROOTDIRNAME,
null,
array(
self::DEFAULTTEMPDIR => array(),
)
);
$this->root_directory = vfsStream::url(self::ROOTDIRNAME);
}
/**
* @covers \SimpleSAML\Utils\System::getOS
* @test
*/
public function testGetOSBasic()
{
$res = System::getOS();
$this->assertInternalType("int", $res);
}
/**
* @covers \SimpleSAML\Utils\System::resolvePath
* @test
*/
public function testResolvePathRemoveTrailingSlashes()
{
$base = "/base////";
$path = "test";
$res = System::resolvePath($path, $base);
$expected = "/base/test";
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\System::resolvePath
* @test
*/
public function testResolvePathPreferAbsolutePathToBase()
{
$base = "/base/";
$path = "/test";
$res = System::resolvePath($path, $base);
$expected = "/test";
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\System::resolvePath
* @test
*/
public function testResolvePathCurDirPath()
{
$base = "/base/";
$path = "/test/.";
$res = System::resolvePath($path, $base);
$expected = "/test";
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\System::resolvePath
* @test
*/
public function testResolvePathParentPath()
{
$base = "/base/";
$path = "/test/child/..";
$res = System::resolvePath($path, $base);
$expected = "/test";
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\System::writeFile
* @test
*/
public function testWriteFileInvalidArguments()
{
$this->setExpectedException('\InvalidArgumentException');
System::writeFile(null, null, null);
}
/**
* @requires PHP 5.4.0
* @covers \SimpleSAML\Utils\System::writeFile
* @test
*/
public function testWriteFileBasic()
{
$tempdir = $this->root_directory . DIRECTORY_SEPARATOR . self::DEFAULTTEMPDIR;
$config = $this->setConfigurationTempDir($tempdir);
$filename = $this->root_directory . DIRECTORY_SEPARATOR . 'test';
System::writeFile($filename, '');
$this->assertFileExists($filename);
$this->clearInstance($config, '\SimpleSAML_Configuration');
}
/**
* @requires PHP 5.4.0
* @covers \SimpleSAML\Utils\System::writeFile
* @test
*/
public function testWriteFileContents()
{
$tempdir = $this->root_directory . DIRECTORY_SEPARATOR . self::DEFAULTTEMPDIR;
$config = $this->setConfigurationTempDir($tempdir);
$filename = $this->root_directory . DIRECTORY_SEPARATOR . 'test';
$contents = 'TEST';
System::writeFile($filename, $contents);
$res = file_get_contents($filename);
$expected = $contents;
$this->assertEquals($expected, $res);
$this->clearInstance($config, '\SimpleSAML_Configuration');
}
/**
* @requires PHP 5.4.0
* @covers \SimpleSAML\Utils\System::writeFile
* @test
*/
public function testWriteFileMode()
{
$tempdir = $this->root_directory . DIRECTORY_SEPARATOR . self::DEFAULTTEMPDIR;
$config = $this->setConfigurationTempDir($tempdir);
$filename = $this->root_directory . DIRECTORY_SEPARATOR . 'test';
$mode = 0666;
System::writeFile($filename, '', $mode);
$res = $this->root->getChild('test')->getPermissions();
$expected = $mode;
$this->assertEquals($expected, $res);
$this->clearInstance($config, '\SimpleSAML_Configuration');
}
/**
* @covers \SimpleSAML\Utils\System::getTempDir
* @test
*/
public function testGetTempDirBasic()
{
$tempdir = $this->root_directory . DIRECTORY_SEPARATOR . self::DEFAULTTEMPDIR;
$config = $this->setConfigurationTempDir($tempdir);
$res = System::getTempDir();
$expected = $tempdir;
$this->assertEquals($expected, $res);
$this->assertFileExists($res);
$this->clearInstance($config, '\SimpleSAML_Configuration');
}
/**
* @covers \SimpleSAML\Utils\System::getTempDir
* @test
*/
public function testGetTempDirNonExistant()
{
$tempdir = $this->root_directory . DIRECTORY_SEPARATOR . 'nonexistant';
$config = $this->setConfigurationTempDir($tempdir);
$res = System::getTempDir();
$expected = $tempdir;
$this->assertEquals($expected, $res);
$this->assertFileExists($res);
$this->clearInstance($config, '\SimpleSAML_Configuration');
}
/**
* @requires PHP 5.4.0
* @requires OS Linux
* @covers \SimpleSAML\Utils\System::getTempDir
* @test
*/
public function testGetTempDirBadOwner()
{
$bad_uid = posix_getuid() + 1;
$tempdir = $this->root_directory . DIRECTORY_SEPARATOR . self::DEFAULTTEMPDIR;
$config = $this->setConfigurationTempDir($tempdir);
chown($tempdir, $bad_uid);
$this->setExpectedException('\SimpleSAML_Error_Exception');
$res = System::getTempDir();
$this->clearInstance($config, '\SimpleSAML_Configuration');
}
private function setConfigurationTempDir($directory)
{
$config = Configuration::loadFromArray(array(
'tempdir' => $directory,
), '[ARRAY]', 'simplesaml');
return $config;
}
protected function clearInstance($service, $className)
{
$reflectedClass = new \ReflectionClass($className);
$reflectedInstance = $reflectedClass->getProperty('instance');
$reflectedInstance->setAccessible(true);
$reflectedInstance->setValue($service, null);
$reflectedInstance->setAccessible(false);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Utils/XMLTest.php 0000644 0000000 0000000 00000022651 13245225037 022115 0 ustar root root assertTrue($res);
}
/**
* @expectedException \InvalidArgumentException
*
* @covers \SimpleSAML\Utils\XML::isDOMNodeOfType
* @test
*/
public function testIsDomNodeOfTypeMissingNamespace()
{
$name = 'name';
$namespace_uri = '@missing';
$element = new \DOMElement($name, 'value', $namespace_uri);
XML::isDOMNodeOfType($element, $name, $namespace_uri);
}
/**
* @covers \SimpleSAML\Utils\XML::isDOMNodeOfType
* @test
*/
public function testIsDomNodeOfTypeEmpty()
{
$name = 'name';
$namespace_uri = '';
$element = new \DOMElement($name);
$res = XML::isDOMNodeOfType($element, $name, $namespace_uri);
$this->assertFalse($res);
}
/**
* @covers \SimpleSAML\Utils\XML::isDOMNodeOfType
* @test
*/
public function testIsDomNodeOfTypeShortcut()
{
$name = 'name';
$namespace_uri = 'urn:oasis:names:tc:SAML:2.0:metadata';
$short_namespace_uri = '@md';
$element = new \DOMElement($name, 'value', $namespace_uri);
$res = XML::isDOMNodeOfType($element, $name, $short_namespace_uri);
$this->assertTrue($res);
}
/**
* @covers \SimpleSAML\Utils\XML::isDOMNodeOfType
* @test
*/
public function testIsDomNodeOfTypeIncorrectName()
{
$name = 'name';
$bad_name = 'bad name';
$namespace_uri = 'ns';
$element = new \DOMElement($name, 'value', $namespace_uri);
$res = XML::isDOMNodeOfType($element, $bad_name, $namespace_uri);
$this->assertFalse($res);
}
/**
* @covers \SimpleSAML\Utils\XML::isDOMNodeOfType
* @test
*/
public function testIsDomNodeOfTypeIncorrectNamespace()
{
$name = 'name';
$namespace_uri = 'ns';
$bad_namespace_uri = 'bad name';
$element = new \DOMElement($name, 'value', $namespace_uri);
$res = XML::isDOMNodeOfType($element, $name, $bad_namespace_uri);
$this->assertFalse($res);
}
/**
* @covers \SimpleSAML\Utils\XML::getDOMText
* @test
*/
public function testGetDomTextBasic()
{
$data = 'root value';
$dom = new \DOMDocument();
$element = $dom->appendChild(new \DOMElement('root'));
$element->appendChild(new \DOMText($data));
$res = XML::getDOMText($element);
$expected = $data;
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\XML::getDOMText
* @test
*/
public function testGetDomTextMulti()
{
$data1 = 'root value 1';
$data2 = 'root value 2';
$dom = new \DOMDocument();
$element = $dom->appendChild(new \DOMElement('root'));
$element->appendChild(new \DOMText($data1));
$element->appendChild(new \DOMText($data2));
$res = XML::getDOMText($element);
$expected = $data1 . $data2 . $data1 . $data2;
$this->assertEquals($expected, $res);
}
/**
* @expectedException \SimpleSAML_Error_Exception
*
* @covers \SimpleSAML\Utils\XML::getDOMText
* @test
*/
public function testGetDomTextIncorrectType()
{
$dom = new \DOMDocument();
$element = $dom->appendChild(new \DOMElement('root'));
$comment = $element->appendChild(new \DOMComment(''));
XML::getDOMText($element);
}
/**
* @covers \SimpleSAML\Utils\XML::getDOMChildren
* @test
*/
public function testGetDomChildrenBasic()
{
$name = 'name';
$namespace_uri = 'ns';
$dom = new \DOMDocument();
$element = new \DOMElement($name, 'value', $namespace_uri);
$dom->appendChild($element);
$res = XML::getDOMChildren($dom, $name, $namespace_uri);
$expected = array($element);
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\XML::getDOMChildren
* @test
*/
public function testGetDomChildrenIncorrectType()
{
$dom = new \DOMDocument();
$text = new \DOMText('text');
$comment = new \DOMComment('comment');
$dom->appendChild($text);
$dom->appendChild($comment);
$res = XML::getDOMChildren($dom, 'name', 'ns');
$this->assertEmpty($res);
}
/**
* @covers \SimpleSAML\Utils\XML::getDOMChildren
* @test
*/
public function testGetDomChildrenIncorrectName()
{
$name = 'name';
$bad_name = 'bad name';
$namespace_uri = 'ns';
$dom = new \DOMDocument();
$element = new \DOMElement($name, 'value', $namespace_uri);
$dom->appendChild($element);
$res = XML::getDOMChildren($dom, $bad_name, $namespace_uri);
$this->assertEmpty($res);
}
/**
* @covers \SimpleSAML\Utils\XML::formatDOMElement
* @test
*/
public function testFormatDomElementBasic()
{
$dom = new \DOMDocument();
$root = new \DOMElement('root');
$dom->appendChild($root);
$root->appendChild(new \DOMText('text'));
XML::formatDOMElement($root);
$res = $dom->saveXML();
$expected = <<<'NOWDOC'
text
NOWDOC;
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\XML::formatDOMElement
* @test
*/
public function testFormatDomElementNested()
{
$dom = new \DOMDocument();
$root = new \DOMElement('root');
$nested = new \DOMElement('nested');
$dom->appendChild($root);
$root->appendChild($nested);
$nested->appendChild(new \DOMText('text'));
XML::formatDOMElement($root);
$res = $dom->saveXML();
$expected = <<<'NOWDOC'
text
NOWDOC;
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\XML::formatDOMElement
* @test
*/
public function testFormatDomElementIndentBase()
{
$indent_base = 'base';
$dom = new \DOMDocument();
$root = new \DOMElement('root');
$nested = new \DOMElement('nested');
$dom->appendChild($root);
$root->appendChild($nested);
$nested->appendChild(new \DOMText('text'));
XML::formatDOMElement($root, $indent_base);
$res = $dom->saveXML();
$expected = <<
$indent_base text
$indent_base
HEREDOC;
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\XML::formatDOMElement
* @test
*/
public function testFormatDomElementTextAndChild()
{
$dom = new \DOMDocument();
$root = new \DOMElement('root');
$dom->appendChild($root);
$root->appendChild(new \DOMText('text'));
$root->appendChild(new \DOMElement('child'));
XML::formatDOMElement($root);
$res = $dom->saveXML();
$expected = <<text
HEREDOC;
$this->assertEquals($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\XML::formatXMLString
* @test
*/
public function testFormatXmlStringBasic()
{
$xml = 'text';
$res = XML::formatXMLString($xml);
$expected = <<<'NOWDOC'
text
NOWDOC;
$this->assertEquals($expected, $res);
}
/**
* @expectedException \DOMException
*
* @covers \SimpleSAML\Utils\XML::formatXMLString
* @test
*/
public function testFormatXmlStringMalformedXml()
{
$xml = 'text';
XML::formatXMLString($xml);
}
/**
* @covers \SimpleSAML\Utils\XML::isValid
* @test
*/
public function testIsValidMalformedXml()
{
$xml = 'text';
$res = XML::isValid($xml, 'unused');
$expected = 'Failed to parse XML string for schema validation';
$this->assertContains($expected, $res);
}
/**
* @covers \SimpleSAML\Utils\XML::isValid
* @test
*/
public function testIsValidMetadata()
{
\SimpleSAML_Configuration::loadFromArray(array(), '[ARRAY]', 'simplesaml');
$schema = 'saml-schema-metadata-2.0.xsd';
$dom = $this->getMockBuilder('\DOMDocument')
->setMethods(array('schemaValidate'))
->disableOriginalConstructor()
->getMock();
/*
* Unfortunately, we cannot actually test schemaValidate. To
* effectively unit test this function we'd have to enable LIBXML_NONET
* which disables network access when loading documents. PHP does not
* currently support enabling this flag.
*/
$dom->method('schemaValidate')
->willReturn(true);
$res = XML::isValid($dom, $schema);
$this->assertTrue($res);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Utils/AttributesTest.php 0000644 0000000 0000000 00000014527 13245225037 023606 0 ustar root root
*/
class AttributesTest extends \PHPUnit_Framework_TestCase
{
/**
* Test the getExpectedAttribute() method with invalid attributes array.
*/
public function testGetExpectedAttributeInvalidAttributesArray()
{
// check with empty array as input
$attributes = 'string';
$expected = 'string';
$this->setExpectedException(
'InvalidArgumentException',
'The attributes array is not an array, it is: '.print_r($attributes, true).'.'
);
Attributes::getExpectedAttribute($attributes, $expected);
}
/**
* Test the getExpectedAttributeMethod() method with invalid expected attribute parameter.
*/
public function testGetExpectedAttributeInvalidAttributeName()
{
// check with invalid attribute name
$attributes = array();
$expected = false;
$this->setExpectedException(
'InvalidArgumentException',
'The expected attribute is not a string, it is: '.print_r($expected, true).'.'
);
Attributes::getExpectedAttribute($attributes, $expected);
}
/**
* Test the getExpectedAttributeMethod() method with a non-normalized attributes array.
*/
public function testGetExpectedAttributeNonNormalizedArray()
{
// check with non-normalized attributes array
$attributes = array(
'attribute' => 'value',
);
$expected = 'attribute';
$this->setExpectedException(
'InvalidArgumentException',
'The attributes array is not normalized, values should be arrays.'
);
Attributes::getExpectedAttribute($attributes, $expected);
}
/**
* Test the getExpectedAttribute() method with valid input but missing expected attribute.
*/
public function testGetExpectedAttributeMissingAttribute()
{
// check missing attribute
$attributes = array(
'attribute' => array('value'),
);
$expected = 'missing';
$this->setExpectedException(
'SimpleSAML_Error_Exception',
"No such attribute '".$expected."' found."
);
Attributes::getExpectedAttribute($attributes, $expected);
}
/**
* Test the getExpectedAttribute() method with an empty attribute.
*/
public function testGetExpectedAttributeEmptyAttribute()
{
// check empty attribute
$attributes = array(
'attribute' => array(),
);
$expected = 'attribute';
$this->setExpectedException(
'SimpleSAML_Error_Exception',
"Empty attribute '".$expected."'.'"
);
Attributes::getExpectedAttribute($attributes, $expected);
}
/**
* Test the getExpectedAttributeMethod() method with multiple values (not being allowed).
*/
public function testGetExpectedAttributeMultipleValues()
{
// check attribute with more than value, that being not allowed
$attributes = array(
'attribute' => array(
'value1',
'value2',
),
);
$expected = 'attribute';
$this->setExpectedException(
'SimpleSAML_Error_Exception',
'More than one value found for the attribute, multiple values not allowed.'
);
Attributes::getExpectedAttribute($attributes, $expected);
}
/**
* Test that the getExpectedAttribute() method successfully obtains values from the attributes array.
*/
public function testGetExpectedAttribute()
{
// check one value
$value = 'value';
$attributes = array(
'attribute' => array($value),
);
$expected = 'attribute';
$this->assertEquals($value, Attributes::getExpectedAttribute($attributes, $expected));
// check multiple (allowed) values
$value = 'value';
$attributes = array(
'attribute' => array($value, 'value2', 'value3'),
);
$expected = 'attribute';
$this->assertEquals($value, Attributes::getExpectedAttribute($attributes, $expected, true));
}
/**
* Test the normalizeAttributesArray() function with input not being an array
*
* @expectedException \InvalidArgumentException
*/
public function testNormalizeAttributesArrayBadInput()
{
Attributes::normalizeAttributesArray('string');
}
/**
* Test the normalizeAttributesArray() function with an array with non-string attribute names.
*
* @expectedException \InvalidArgumentException
*/
public function testNormalizeAttributesArrayBadKeys()
{
Attributes::normalizeAttributesArray(array('attr1' => 'value1', 1 => 'value2'));
}
/**
* Test the normalizeAttributesArray() function with an array with non-string attribute values.
*
* @expectedException \InvalidArgumentException
*/
public function testNormalizeAttributesArrayBadValues()
{
Attributes::normalizeAttributesArray(array('attr1' => 'value1', 'attr2' => 0));
}
/**
* Test the normalizeAttributesArray() function.
*/
public function testNormalizeAttributesArray()
{
$attributes = array(
'key1' => 'value1',
'key2' => array('value2', 'value3'),
'key3' => 'value1'
);
$expected = array(
'key1' => array('value1'),
'key2' => array('value2', 'value3'),
'key3' => array('value1')
);
$this->assertEquals(
$expected,
Attributes::normalizeAttributesArray($attributes),
'Attribute array normalization failed'
);
}
/**
* Test the getAttributeNamespace() function.
*/
public function testNamespacedAttributes()
{
// test for only the name
$this->assertEquals(
array('default', 'name'),
Attributes::getAttributeNamespace('name', 'default')
);
// test for a given namespace and multiple '/'
$this->assertEquals(
array('some/namespace', 'name'),
Attributes::getAttributeNamespace('some/namespace/name', 'default')
);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Metadata/ 0000755 0000000 0000000 00000000000 13245225037 020516 5 ustar root root simplesamlphp-1.15.3/tests/lib/SimpleSAML/Metadata/SAMLBuilderTest.php 0000644 0000000 0000000 00000017451 13245225037 024142 0 ustar root root $entityId,
'name' => array('en' => 'Test SP'),
'metadata-set' => $set,
'attributes' => array(
'urn:oid:1.3.6.1.4.1.5923.1.1.1.10',
'urn:oid:1.3.6.1.4.1.5923.1.1.1.6',
'urn:oid:0.9.2342.19200300.100.1.3',
'urn:oid:2.5.4.3',
),
);
$samlBuilder = new SimpleSAML_Metadata_SAMLBuilder($entityId);
$samlBuilder->addMetadata($set, $metadata);
$spDesc = $samlBuilder->getEntityDescriptor();
$acs = $spDesc->getElementsByTagName("AttributeConsumingService");
$this->assertEquals(1, $acs->length);
$attributes = $acs->item(0)->getElementsByTagName("RequestedAttribute");
$this->assertEquals(4, $attributes->length);
for ($c = 0; $c < $attributes->length; $c++) {
$curAttribute = $attributes->item($c);
$this->assertTrue($curAttribute->hasAttribute("Name"));
$this->assertFalse($curAttribute->hasAttribute("FriendlyName"));
$this->assertEquals($metadata['attributes'][$c], $curAttribute->getAttribute("Name"));
}
// test SP20 array parsing, no friendly name
$set = 'saml20-sp-remote';
$metadata = array(
'entityid' => $entityId,
'name' => array('en' => 'Test SP'),
'metadata-set' => $set,
'attributes' => array(
'eduPersonTargetedID' => 'urn:oid:1.3.6.1.4.1.5923.1.1.1.10',
'eduPersonPrincipalName' => 'urn:oid:1.3.6.1.4.1.5923.1.1.1.6',
'eduPersonOrgDN' => 'urn:oid:0.9.2342.19200300.100.1.3',
'cn' => 'urn:oid:2.5.4.3',
),
);
$samlBuilder = new SimpleSAML_Metadata_SAMLBuilder($entityId);
$samlBuilder->addMetadata($set, $metadata);
$spDesc = $samlBuilder->getEntityDescriptor();
$acs = $spDesc->getElementsByTagName("AttributeConsumingService");
$this->assertEquals(1, $acs->length);
$attributes = $acs->item(0)->getElementsByTagName("RequestedAttribute");
$this->assertEquals(4, $attributes->length);
$keys = array_keys($metadata['attributes']);
for ($c = 0; $c < $attributes->length; $c++) {
$curAttribute = $attributes->item($c);
$this->assertTrue($curAttribute->hasAttribute("Name"));
$this->assertTrue($curAttribute->hasAttribute("FriendlyName"));
$this->assertEquals($metadata['attributes'][$keys[$c]], $curAttribute->getAttribute("Name"));
$this->assertEquals($keys[$c], $curAttribute->getAttribute("FriendlyName"));
}
// test SP13 array parsing, no friendly name
$set = 'shib13-sp-remote';
$metadata = array(
'entityid' => $entityId,
'name' => array('en' => 'Test SP'),
'metadata-set' => $set,
'attributes' => array(
'urn:oid:1.3.6.1.4.1.5923.1.1.1.10',
'urn:oid:1.3.6.1.4.1.5923.1.1.1.6',
'urn:oid:0.9.2342.19200300.100.1.3',
'urn:oid:2.5.4.3',
),
);
$samlBuilder = new SimpleSAML_Metadata_SAMLBuilder($entityId);
$samlBuilder->addMetadata($set, $metadata);
$spDesc = $samlBuilder->getEntityDescriptor();
$acs = $spDesc->getElementsByTagName("AttributeConsumingService");
$this->assertEquals(1, $acs->length);
$attributes = $acs->item(0)->getElementsByTagName("RequestedAttribute");
$this->assertEquals(4, $attributes->length);
for ($c = 0; $c < $attributes->length; $c++) {
$curAttribute = $attributes->item($c);
$this->assertTrue($curAttribute->hasAttribute("Name"));
$this->assertFalse($curAttribute->hasAttribute("FriendlyName"));
$this->assertEquals($metadata['attributes'][$c], $curAttribute->getAttribute("Name"));
}
// test SP20 array parsing, no friendly name
$set = 'shib13-sp-remote';
$metadata = array(
'entityid' => $entityId,
'name' => array('en' => 'Test SP'),
'metadata-set' => $set,
'attributes' => array(
'eduPersonTargetedID' => 'urn:oid:1.3.6.1.4.1.5923.1.1.1.10',
'eduPersonPrincipalName' => 'urn:oid:1.3.6.1.4.1.5923.1.1.1.6',
'eduPersonOrgDN' => 'urn:oid:0.9.2342.19200300.100.1.3',
'cn' => 'urn:oid:2.5.4.3',
),
);
$samlBuilder = new SimpleSAML_Metadata_SAMLBuilder($entityId);
$samlBuilder->addMetadata($set, $metadata);
$spDesc = $samlBuilder->getEntityDescriptor();
$acs = $spDesc->getElementsByTagName("AttributeConsumingService");
$this->assertEquals(1, $acs->length);
$attributes = $acs->item(0)->getElementsByTagName("RequestedAttribute");
$this->assertEquals(4, $attributes->length);
$keys = array_keys($metadata['attributes']);
for ($c = 0; $c < $attributes->length; $c++) {
$curAttribute = $attributes->item($c);
$this->assertTrue($curAttribute->hasAttribute("Name"));
$this->assertTrue($curAttribute->hasAttribute("FriendlyName"));
$this->assertEquals($metadata['attributes'][$keys[$c]], $curAttribute->getAttribute("Name"));
$this->assertEquals($keys[$c], $curAttribute->getAttribute("FriendlyName"));
}
}
/**
* Test the required protocolSupportEnumeration in AttributeAuthorityDescriptor
*/
public function testProtocolSupportEnumeration()
{
$entityId = 'https://entity.example.com/id';
$set = 'attributeauthority-remote';
// without protocolSupportEnumeration fallback to default: urn:oasis:names:tc:SAML:2.0:protocol
$metadata = array(
'entityid' => $entityId,
'name' => array('en' => 'Test AA'),
'metadata-set' => $set,
'AttributeService' =>
array (
0 =>
array (
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP',
'Location' => 'https://entity.example.com:8443/idp/profile/SAML2/SOAP/AttributeQuery',
),
),
);
$samlBuilder = new SimpleSAML_Metadata_SAMLBuilder($entityId);
$samlBuilder->addMetadata($set, $metadata);
$entityDescriptorXml = $samlBuilder->getEntityDescriptorText();
$this->assertRegExp(
'//',
$entityDescriptorXml
);
// explicit protocols
$metadata['protocols'] =
array(
0 => 'urn:oasis:names:tc:SAML:1.1:protocol',
1 => 'urn:oasis:names:tc:SAML:2.0:protocol',
);
$samlBuilder = new SimpleSAML_Metadata_SAMLBuilder($entityId);
$samlBuilder->addMetadata($set, $metadata);
$entityDescriptorXml = $samlBuilder->getEntityDescriptorText();
$this->assertRegExp(
'//',
$entityDescriptorXml
);
}
}
simplesamlphp-1.15.3/tests/lib/SimpleSAML/Metadata/SAMLParserTest.php 0000644 0000000 0000000 00000012624 13245225037 024005 0 ustar root root 'https://incommon.org',
);
$document = \SAML2\DOMDocumentFactory::fromString(
<<
XML
);
$entities = \SimpleSAML_Metadata_SAMLParser::parseDescriptorsElement($document->documentElement);
$this->assertArrayHasKey('theEntityID', $entities);
// RegistrationInfo is accessible in the SP or IDP metadata accessors
$metadata = $entities['theEntityID']->getMetadata20SP();
$this->assertEquals($expected, $metadata['RegistrationInfo']);
}
/**
* Test RegistrationInfo is inherited correctly from parent EntitiesDescriptor.
* According to the spec overriding RegistrationInfo is not valid. We ignore attempts to override
*/
public function testRegistrationInfoInheritance()
{
$expected = array(
'registrationAuthority' => 'https://incommon.org',
);
$document = \SAML2\DOMDocumentFactory::fromString(
<<
XML
);
$entities = \SimpleSAML_Metadata_SAMLParser::parseDescriptorsElement($document->documentElement);
$this->assertArrayHasKey('theEntityID', $entities);
$this->assertArrayHasKey('subEntityId', $entities);
// RegistrationInfo is accessible in the SP or IDP metadata accessors
$metadata = $entities['theEntityID']->getMetadata20SP();
$this->assertEquals($expected, $metadata['RegistrationInfo']);
$metadata = $entities['subEntityId']->getMetadata20SP();
$this->assertEquals($expected, $metadata['RegistrationInfo']);
$metadata = $entities['subEntityIdOverride']->getMetadata20SP();
$this->assertEquals($expected, $metadata['RegistrationInfo']);
}
/**
* Test AttributeConsumingService is parsed
*/
public function testAttributeConsumingServiceParsing()
{
$document = \SAML2\DOMDocumentFactory::fromString(
<<Example serviceDit is een voorbeeld voor de unittest.
XML
);
$entities = \SimpleSAML_Metadata_SAMLParser::parseDescriptorsElement($document->documentElement);
$this->assertArrayHasKey('theEntityID', $entities);
$metadata = $entities['theEntityID']->getMetadata20SP();
$this->assertEquals("Example service", $metadata['name']['en']);
$this->assertEquals("Dit is een voorbeeld voor de unittest.", $metadata['description']['nl']);
$expected_a = array("urn:mace:dir:attribute-def:eduPersonPrincipalName", "urn:mace:dir:attribute-def:mail", "urn:mace:dir:attribute-def:displayName");
$expected_r = array("urn:mace:dir:attribute-def:eduPersonPrincipalName");
$this->assertEquals($expected_a, $metadata['attributes']);
$this->assertEquals($expected_r, $metadata['attributes.required']);
}
}
simplesamlphp-1.15.3/tests/routers/ 0000755 0000000 0000000 00000000000 13245225037 016025 5 ustar root root simplesamlphp-1.15.3/tests/routers/configLoader.php 0000644 0000000 0000000 00000003326 13245225037 021136 0 ustar root root start();
* 3. Get the PID of the server once it has started:
* $pid = $server->getPid();
* 4. Build the path to the file that this script will use:
* $file = sys_get_temp_dir().'/'.$pid.'.lock';
* 5. Dump the configuration array to the file:
* file_put_contents("get($query, $parameters);
* 7. Remove the temporary file when done:
* unlink($file);
*/
include_once(sys_get_temp_dir().'/'.getmypid().'.lock');
// load SimpleSAMLphp's autoloader
require_once(dirname(__FILE__).'/../../vendor/autoload.php');
// initialize configuration
if (isset($config)) {
SimpleSAML_Configuration::loadFromArray($config, '[ARRAY]', 'simplesaml');
}
// let the script proceed
// see: http://php.net/manual/en/features.commandline.webserver.php
return false;
simplesamlphp-1.15.3/tests/Utils/ 0000755 0000000 0000000 00000000000 13245225037 015422 5 ustar root root simplesamlphp-1.15.3/tests/Utils/StateClearer.php 0000644 0000000 0000000 00000004254 13245225037 020516 0 ustar root root backups['$_COOKIE'] = $_COOKIE;
$this->backups['$_ENV'] = $_ENV;
$this->backups['$_FILES'] = $_FILES;
$this->backups['$_GET'] = $_GET;
$this->backups['$_POST'] = $_POST;
$this->backups['$_SERVER'] = $_SERVER;
$this->backups['$_SESSION'] = isset($_SESSION) ? $_SESSION : array();
$this->backups['$_REQUEST'] = $_REQUEST;
}
/**
* Clear any global state.
*/
public function clearGlobals()
{
if (!empty($this->backups)) {
$_COOKIE = $this->backups['$_COOKIE'];
$_ENV = $this->backups['$_ENV'];
$_FILES = $this->backups['$_FILES'];
$_GET = $this->backups['$_GET'];
$_POST = $this->backups['$_POST'];
$_SERVER = $this->backups['$_SERVER'];
$_SESSION = $this->backups['$_SESSION'];
$_REQUEST = $this->backups['$_REQUEST'];
} else {
//TODO: what should this behavior be?
}
}
/**
* Clear any SSP specific state, such as SSP enviormental variables or cached internals.
*/
public function clearSSPState()
{
foreach ($this->clearableState as $var) {
$var::clearInternalState();
}
foreach ($this->vars_to_unset as $var) {
putenv($var);
}
}
}
simplesamlphp-1.15.3/tests/Utils/ReduceSpillOverTest.php 0000644 0000000 0000000 00000002103 13245225037 022036 0 ustar root root 'b'), '[ARRAY]', 'simplesaml');
$this->assertEquals('b', \SimpleSAML_Configuration::getInstance()->getString('a'));
putenv('SIMPLESAMLPHP_CONFIG_DIR=' . __DIR__);
}
/**
* Confirm global state removed prior to next test
*/
public function testStateRemoved()
{
$this->assertArrayNotHasKey('QUERY_STRING', $_SERVER);
$this->assertFalse(getenv('SIMPLESAMLPHP_CONFIG_DIR'));
try {
\SimpleSAML_Configuration::getInstance();
$this->fail('Expected config configured in other tests to no longer be valid');
} catch (\SimpleSAML\Error\ConfigurationError $error) {
// Expected error
}
}
}
simplesamlphp-1.15.3/tests/Utils/ClearStateTestCase.php 0000644 0000000 0000000 00000001714 13245225037 021621 0 ustar root root backupGlobals();
}
}
protected function setUp()
{
self::clearState();
}
public static function tearDownAfterClass()
{
self::clearState();
}
/**
* Clear any SSP global state to reduce spill over between tests.
*/
public static function clearState()
{
self::$stateClearer->clearGlobals();
self::$stateClearer->clearSSPState();
}
}
simplesamlphp-1.15.3/docs/ 0000755 0000000 0000000 00000000000 13245225037 014110 5 ustar root root simplesamlphp-1.15.3/docs/index.md 0000644 0000000 0000000 00000006314 13245225037 015545 0 ustar root root SimpleSAMLphp Documentation
===========================
* [Installing SimpleSAMLphp](simplesamlphp-install)
* [Upgrade notes for version 1.15](simplesamlphp-upgrade-notes-1.15)
* [Upgrade notes for version 1.14](simplesamlphp-upgrade-notes-1.14)
* [Upgrade notes for version 1.13](simplesamlphp-upgrade-notes-1.13)
* [Upgrade notes for version 1.12](simplesamlphp-upgrade-notes-1.12)
* [Upgrade notes for version 1.11](simplesamlphp-upgrade-notes-1.11)
* [Upgrade notes for version 1.10](simplesamlphp-upgrade-notes-1.10)
* [Upgrade notes for version 1.9](simplesamlphp-upgrade-notes-1.9)
* [Upgrade notes for version 1.8](simplesamlphp-upgrade-notes-1.8)
* [Upgrade notes for version 1.7](simplesamlphp-upgrade-notes-1.7)
* [Upgrade notes for version 1.6](simplesamlphp-upgrade-notes-1.6)
* [Upgrade notes for version 1.5](simplesamlphp-upgrade-notes-1.5)
* [Installation from the repository](simplesamlphp-install-repo)
* [Changelog](simplesamlphp-changelog)
* [Using SimpleSAMLphp as a SAML Service Provider](simplesamlphp-sp)
* [Hosted SP Configuration Reference](./saml:sp)
* [IdP remote reference](simplesamlphp-reference-idp-remote)
* [Upgrading - migration to use the SAML authentication source](simplesamlphp-sp-migration)
* [Configuring HTTP-Artifact](./simplesamlphp-artifact-sp)
* [Using scoping](./simplesamlphp-scoping)
* [Holder-of-Key profile](simplesamlphp-hok-sp)
* [Identity Provider QuickStart](simplesamlphp-idp)
* [IdP hosted reference](simplesamlphp-reference-idp-hosted)
* [SP remote reference](simplesamlphp-reference-sp-remote)
* [Use case: Setting up an IdP for G Suite (Google Apps)](simplesamlphp-googleapps)
* [Configuring HTTP-Artifact](./simplesamlphp-artifact-idp)
* [Identity Provider Advanced Topics](simplesamlphp-idp-more)
* [Holder-of-Key profile](simplesamlphp-hok-idp)
* [Automated Metadata Management](simplesamlphp-automated_metadata)
* [Maintenance and configuration](simplesamlphp-maintenance) - covers session handling, php configuration etc.
* [Authentication Processing Filters](simplesamlphp-authproc) - attribute filtering, attribute mapping, consent, group generation etc.
* [Advanced features](simplesamlphp-advancedfeatures) - covers bridging protocols, attribute filtering, etc.
* [State Information Lost](simplesamlphp-nostate) - more about this common error message
* [SimpleSAMLphp Dictionaries and Translation](simplesamlphp-translation)
* [Theming SimpleSAMLphp](simplesamlphp-theming)
* [SimpleSAMLphp Modules](simplesamlphp-modules) - how to create own customized modules
* [Key rollover](./saml:keyrollover)
* [Creating authentication sources](./simplesamlphp-authsource)
* [Implementing custom username/password authentication](./simplesamlphp-customauth)
* [Storing sessions in Riak](./riak:simplesamlphp-riak)
Documentation on specific SimpleSAMLphp modules:
* [Consent module](./consent:consent)
* [Installing and configuring the consentAdmin module](./consentAdmin:consentAdmin)
* [Authorization](./authorize:authorize)
* [autotest Module](./autotest:test)
* [Statistics](./statistics:statistics)
Documentation for SimpleSAMLphp developers:
* [Error handling in SimpleSAMLphp](simplesamlphp-errorhandling)
simplesamlphp-1.15.3/docs/simplesamlphp-upgrade-notes-1.11.md 0000644 0000000 0000000 00000000373 13245225037 022444 0 ustar root root Upgrade notes for SimpleSAMLphp 1.11
====================================
* Support for the Holder-of-Key profile in the SAML 2.0 SP has been disabled by default.
To enable it, set `saml20.hok.assertion` to `TRUE` in `config/authsources.php`.
simplesamlphp-1.15.3/docs/simplesamlphp-upgrade-notes-1.12.md 0000644 0000000 0000000 00000000160 13245225037 022437 0 ustar root root Upgrade notes for SimpleSAMLphp 1.12
====================================
* PHP version 5.3 is now required.
simplesamlphp-1.15.3/docs/simplesamlphp-upgrade-notes-1.7.md 0000644 0000000 0000000 00000001530 13245225037 022365 0 ustar root root Upgrade notes for SimpleSAMLphp 1.7
===================================
* The attribute names generated by the twitter and facebook authentication sources have changed.
* Several new options have been added to config.php, and some have been renamed.
The old options should still work, but it is suggested that you look at the config.php file in config-templates, and compare it to your own.
* There have been several changes to the internal API.
Most of the changes will not be noticed by the application using SimpleSAMLphp.
See the changelog for more details about the changes.
* Relative redirects are no longer supported.
If your application passes relative URL's to the `SimpleSAML_Utilities::redirect()`-function, it will no longer work.
This also applies if you pass relative URL's to other functions that do redirects.
simplesamlphp-1.15.3/docs/simplesamlphp-errorhandling.md 0000644 0000000 0000000 00000027152 13245225037 022153 0 ustar root root Exception and error handling in SimpleSAMLphp
=============================================
This document describes the way errors and exceptions are handled in authentication sources and authentication processing filters.
The basic goal is to be able to throw an exception during authentication, and then have that exception transported back to the SP in a way that the SP understands.
This means that internal SimpleSAMLphp exceptions must be mapped to transport specific error codes for the various transports that are supported by SimpleSAMLphp.
E.g.: When a `SimpleSAML_Error_NoPassive` error is thrown by an authentication processing filter in a SAML 2.0 IdP, we want to map that exception to the `urn:oasis:names:tc:SAML:2.0:status:NoPassive` status code.
That status code should then be returned to the SP.
Throwing exceptions
-------------------
How you throw an exception depends on where you want to throw it from.
The simplest case is if you want to throw it during the `authenticate()`-method in an authentication module or during the `process()`-method in a processing filter.
In those methods, you can just throw an exception:
public function process(&$state) {
if ($state['something'] === FALSE) {
throw new SimpleSAML_Error_Exception('Something is wrong...');
}
}
Exceptions thrown at this stage will be caught and delivered to the appropriate error handler.
If you want to throw an exception outside of those methods, i.e. after you have done a redirect, you need to use the `SimpleSAML_Auth_State::throwException()` function:
The `SimpleSAML_Auth_State::throwException` function will then transfer your exception to the appropriate error handler.
### Note
Note that we use the `SimpleSAML_Error_Exception` class in both cases.
This is because the delivery of the exception may require a redirect to a different web page.
In those cases, the exception needs to be serialized.
The normal `Exception` class in PHP isn't always serializable.
If you throw an exception that isn't a subclass of the `SimpleSAML_Error_Exception` class, your exception will be converted to an instance of `SimpleSAML_Error_UnserializableException`.
The `SimpleSAML_Auth_State::throwException` function does not accept any exceptions that does not subclass the `SimpleSAML_Error_Exception` class.
Returning specific SAML 2 errors
--------------------------------
By default, all thrown exceptions will be converted to a generic SAML 2 error.
In some cases, you may want to convert the exception to a specific SAML 2 status code.
For example, the `SimpleSAML_Error_NoPassive` exception should be converted to a SAML 2 status code with the following properties:
* The top-level status code should be `urn:oasis:names:tc:SAML:2.0:status:Responder`.
* The second-level status code should be `urn:oasis:names:tc:SAML:2.0:status:NoPassive`.
* The status message should contain the cause of the exception.
The `sspmod_saml_Error` class represents SAML 2 errors.
It represents a SAML 2 status code with three elements: the top-level status code, the second-level status code and the status message.
The second-level status code and the status message is optional, and can be `NULL`.
The `sspmod_saml_Error` class contains a helper function named `fromException`.
The `fromException()` function is used by `www/saml2/idp/SSOService.php` to return SAML 2 errors to the SP.
The function contains a list which maps various exceptions to specific SAML 2 errors.
If it is unable to convert the exception, it will return a generic SAML 2 error describing the original exception in its status message.
To return a specific SAML 2 error, you should:
* Create a new exception class for your error. This exception class must subclass `SimpleSAML_Error_Exception`.
* Add that exception to the list in `fromException()`.
* Consider adding the exception to `toException()` in the same file. (See the next section.)
### Note
While it is possible to throw SAML 2 errors directly from within authentication sources and processing filters, this practice is discouraged.
Throwing SAML 2 errors will tie your code directly to the SAML 2 protocol, and it may be more difficult to use with other protocols.
Converting SAML 2 errors to normal exceptions
---------------------------------------------
On the SP side, we want to convert SAML 2 errors to SimpleSAMLphp exceptions again.
This is handled by the `toException()` method in `sspmod_saml_Error`.
The assertion consumer script of the SAML 2 authentication source (`modules/saml2/sp/acs.php`) uses this method.
The result is that generic exceptions are thrown from that authentication source.
For example, `NoPassive` errors will be converted back to instances of `SimpleSAML_Error_NoPassive`.
Other protocols
---------------
The error handling code has not yet been added to other protocols, but the framework should be easy to adapt for other protocols.
To eventually support other protocols was a goal when designing this framework.
Technical details
-----------------------
This section attempts to describe the internals of the error handling framework.
### `SimpleSAML_Error_Exception`
The `SimpleSAML_Error_Exception` class extends the normal PHP `Exception` class.
It makes the exceptions serializable by overriding the `__sleep()` method.
The `__sleep()` method returns all variables in the class which should be serialized when saving the class.
To make sure that the class is serializable, we remove the `$trace` variable from the serialization.
The `$trace` variable contains the full stack trace to the point where the exception was instantiated.
This can be a problem, since the stack trace also contains the parameters to the function calls.
If one of the parameters in unserializable, serialization of the exception will fail.
Since preserving the stack trace can be useful for debugging, we save a variant of the stack trace in the `$backtrace` variable.
This variable can be accessed through the `getBacktrace()` method.
It returns an array with one line of text for each function call in the stack, ending on the point where the exception was created.
#### Note
Since we lose the original `$trace` variable during serialization, PHP will fill it with a new stack trace when the exception is unserialized.
This may be confusing since the new stack trace leads into the `unserialize()` function.
It is therefore recommended to use the getBacktrace() method.
### `SimpleSAML_Auth_State`
There are two methods in this class that deals with exceptions:
* `throwException($state, $exception)`, which throws an exception.
* `loadExceptionState($id)`, which restores a state containing an exception.
#### `throwException`
This method delivers the exception to the code that initialized the exception handling in the authentication state.
That would be `SimpleSAML_Auth_Default` for authtentication sources, and `www/saml2/idp/SSOService.php` for processing filters.
To configure how and where the exception should be delivered, there are two fields in the state-array which can be set:
* `SimpleSAML_Auth_State::EXCEPTION_HANDLER_FUNC`, in which case the exception will be delivered by a function call to the function specified in that field.
* `SimpleSAML_Auth_State::EXCEPTION_HANDLER_URL`, in which case the exception will be delivered by a redirect to the URL specified in that field.
If the exception is delivered by a function call, the function will be called with two parameters: The exception and the state array.
If the exception is delivered by a redirect, SimpleSAML_Auth_State will save the exception in a field in the state array, pass a parameter with the id of the state array to the URL.
The `SimpleSAML_Auth_State::EXCEPTION_PARAM` constant contains the name of that parameter, while the `SimpleSAML_Auth_State::EXCEPTION_DATA` constant holds the name of the field where the exception is saved.
#### `loadException`
To retrieve the exception, the application should check for the state parameter in the request, and then retrieve the state array by calling `SimpleSAML_Auth_State::loadExceptionState()`.
The exception can be located in a field named `SimpleSAML_Auth_State::EXCEPTION_DATA`.
The following code illustrates this behaviour:
if (array_key_exists(SimpleSAML_Auth_State::EXCEPTION_PARAM, $_REQUEST)) {
$state = SimpleSAML_Auth_State::loadExceptionState();
$exception = $state[SimpleSAML_Auth_State::EXCEPTION_DATA];
/* Process exception. */
}
### `SimpleSAML_Auth_Default`
This class accepts an `$errorURL` parameter to the `initLogin()` function.
This parameter is stored in the `SimpleSAML_Auth_State::EXCEPTION_HANDLER_URL` of the state array.
Exceptions thrown by the authentication source will be delivered to that URL.
It also wraps the call to the `authenticate()` function inside a try-catch block.
Any exceptions thrown during that function call will be delivered to the URL specified in the `$errorURL` parameter.
This is done for consistency, since `SimpleSAML_Auth_Default` never transfers control back to the caller by returning.
### `SimpleSAML_Auth_ProcessingChain`
This class requires the caller to add the error handler to the state array before calling the `processState()` function.
Exceptions thrown by the processing filters will be delivered directly to the caller of `processState()` if possible.
However, if one of the filters in the processing chain redirected the user away from the caller, exceptions will be delivered through the error handler saved in the state array.
This is the same behaviour as normal processing filters.
The result will be delivered directly if it is possible, but if not, it will be delivered through a redirect.
The code for handling this becomes something like:
if (array_key_exists(SimpleSAML_Auth_State::EXCEPTION_PARAM, $_REQUEST)) {
$state = SimpleSAML_Auth_State::loadExceptionState();
$exception = $state[SimpleSAML_Auth_State::EXCEPTION_DATA];
/* Handle exception... */
[...]
}
$procChain = [...];
$state = array(
'ReturnURL' => SimpleSAML_Utilities::selfURLNoQuery(),
SimpleSAML_Auth_State::EXCEPTION_HANDLER_URL => SimpleSAML_Utilities::selfURLNoQuery(),
[...],
)
try {
$procChain->processState($state);
} catch (SimpleSAML_Error_Exception $e) {
/* Handle exception. */
[...];
}
#### Note
An exception which isn't a subclass of `SimpleSAML_Error_Exception` will be converted to the `SimpleSAML_Error_UnserializedException` class.
This happens regardless of whether the exception is delivered directly or through the error handler.
This is done to be consistent in what the application receives - now it will always receive the same exception, regardless of whether it is delivered directly or through a redirect.
Custom error show function
--------------------------
Optional custom error show function, called from SimpleSAML_Error_Error::show, is defined with 'errors.show_function' in config.php.
Example code for this function, which implements the same functionality as SimpleSAML_Error_Error::show, looks something like:
public static function show(SimpleSAML_Configuration $config, array $data) {
$t = new SimpleSAML_XHTML_Template($config, 'error.php', 'errors');
$t->data = array_merge($t->data, $data);
$t->show();
exit;
}
simplesamlphp-1.15.3/docs/simplesamlphp-advancedfeatures.md 0000644 0000000 0000000 00000015107 13245225037 022616 0 ustar root root SimpleSAMLphp Advanced Features
===============================
SimpleSAMLphp documentation
---------------------------
This document is part of the SimpleSAMLphp documentation suite.
- [List of all SimpleSAMLphp documentation](http://simplesamlphp.org/docs)
This document assumes that you already have a installation of
SimpleSAMLphp running, configured and working. This is the next
step :)
Bridging between protocols
--------------------------
A bridge between two protocols is built using both an IdP and an SP, connected together.
To let a SAML 2.0 SP talk to a SAML 1.1 IdP, you build a SimpleSAMLphp bridge from a SAML 2.0 IdP and a SAML 1.1 SP.
The SAML 2.0 SP talks to the SAML 2.0 IdP, which hands the request over to the SAML 1.1 SP, which forwards it to the SAML 1.1 IdP.
If you have followed the instructions for setting up an SP, and have configured an authentication source, all you need to do is to add that authentication source to the IdP.
**Example of bridge configuration**
In `metadata/saml20-idp-hosted.php`:
'auth' => 'default-sp',
In `config/authsources.php`:
'default-sp' => array(
'saml:SP',
),
Attribute control
-----------------
Filtering, mapping, etc can be performed by using existing or create new *Authentication Processing Filters*. For more information, read:
* [Authentication Processing Filters in SimpleSAMLphp](simplesamlphp-authproc)
Automatic update of SAML 2.0 Metadata XML from HTTPS
----------------------------------------------------
The `metarefresh` module is the preferred method for doing this.
Please see the [metarefresh documentation](simplesamlphp-automated_metadata).
Using simpleSAMLphp on a web server requiring the use of a web proxy
--------------------------------------------------------------------
Some modules in simpleSAMLphp may require fetching HTTP/HTTPS content from external websites (e.g. the metarefresh module needs to fetch the metadata from an external source).
simpleSAMLphp can be configured to send HTTP/S requests via such a proxy. The proxy can be configured in the config/config.php option "proxy". Should the proxy require authentication, this can be configured with "proxy.auth".
The default is not to use a proxy ('proxy' = null) and no username and password are used ('proxy.auth' = false).
Auth MemCookie
--------------
[Auth MemCookie](http://authmemcookie.sourceforge.net/) support is deprecated in the standard code base of SimpleSAMLphp
and will no longer be available starting in SimpleSAMLphp 2.0. Please use the new
[memcookie module](https://github.com/simplesamlphp/simplesamlphp-module-memcookie) instead.
Metadata signing
----------------
SimpleSAMLphp supports signing of the metadata it generates. Metadata signing is configured by four options:
- `metadata.sign.enable`: Whether metadata signing should be enabled or not. Set to `TRUE` to enable metadata signing. Defaults to `FALSE`.
- `metadata.sign.privatekey`: Name of the file with the private key which should be used to sign the metadata. This file must exist in in the `cert` directory.
- `metadata.sign.privatekey_pass`: Passphrase which should be used to open the private key. This parameter is optional, and should be left out if the private key is unencrypted.
- `metadata.sign.certificate`: Name of the file with the certificate which matches the private key. This file must exist in in the `cert` directory.
- `metadata.sign.algorithm`: The algorithm to use when signing metadata for this entity. Defaults to RSA-SHA1. Possible values:
* `http://www.w3.org/2000/09/xmldsig#rsa-sha1`
*Note*: the use of SHA1 is **deprecated** and will be disallowed in the future.
* `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`
These options can be configured globally in the `config/config.php`-file, or per SP/IdP by adding them to the hosted metadata for the SP/IdP. The configuration in the metadata for the SP/IdP takes precedence over the global configuration.
There is also an additional fallback for the private key and the certificate. If `metadata.sign.privatekey` and `metadata.sign.certificate` isn't configured, SimpleSAMLphp will use the `privatekey`, `privatekey_pass` and `certificate` options in the metadata for the SP/IdP.
Session checking function
-------------------------
Optional session checking function, called on session init and loading, defined with 'session.check_function' in config.php.
Example code for the function with GeoIP country check:
public static function checkSession($session, $init = FALSE) {
$data_type = 'example:check_session';
$data_key = 'remote_addr';
$remote_addr = NULL;
if (!empty($_SERVER['REMOTE_ADDR'])) {
$remote_addr = (string)$_SERVER['REMOTE_ADDR'];
}
if ($init) {
$session->setData($data_type, $data_key, $remote_addr, SimpleSAML_Session::DATA_TIMEOUT_SESSION_END);
return;
}
if (!function_exists('geoip_country_code_by_name')) {
SimpleSAML\Logger::warning('geoip php module required.');
return TRUE;
}
$stored_remote_addr = $session->getData($data_type, $data_key);
if ($stored_remote_addr === NULL) {
SimpleSAML\Logger::warning('Stored data not found.');
return FALSE;
}
$country_a = geoip_country_code_by_name($remote_addr);
$country_b = geoip_country_code_by_name($stored_remote_addr);
if ($country_a === $country_b) {
if ($stored_remote_addr !== $remote_addr) {
$session->setData($data_type, $data_key, $remote_addr, SimpleSAML_Session::DATA_TIMEOUT_SESSION_END);
}
return TRUE;
}
return FALSE;
}
Support
-------
If you need help to make this work, or want to discuss
SimpleSAMLphp with other users of the software, you are fortunate:
Around SimpleSAMLphp there is a great Open source community, and
you are welcome to join! The forums are open for you to ask
questions, contribute answers other further questions, request
improvements or contribute with code or plugins of your own.
- [SimpleSAMLphp homepage](https://simplesamlphp.org)
- [List of all available SimpleSAMLphp documentation](https://simplesamlphp.org/docs/)
- [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
simplesamlphp-1.15.3/docs/simplesamlphp-sp-migration.md 0000644 0000000 0000000 00000023010 13245225037 021713 0 ustar root root Migrating to the `saml` module
==============================
This document describes how you can migrate your code to use the `saml` module for authentication against SAML 2.0 and SAML 1.1 IdPs.
It assumes that you have previously set up a SP by using redirects to `saml2/sp/initSSO.php`.
The steps we are going to follow are:
1. Create a new authentication source.
2. Add the metadata for this authentication source to the IdP.
3. Test the new authentication source.
4. Convert the application to use the new API.
5. Test the application.
6. Remove the old metadata from the IdP.
7. Disable the old SAML 2 SP.
Create a new authentication source
----------------------------------
In this step we are going to create an authentication source which uses the `saml` module for authentication.
To do this, we open `config/authsources.php`. Create the file if it does not exist.
If you create the file, it should look like this:
array(
'saml:SP',
/*
* The entity ID of this SP.
* Can be NULL/unset, in which case an entity ID is generated based on the metadata URL.
*/
'entityID' => NULL,
/*
* The entity ID of the IdP this should SP should contact.
* Can be NULL/unset, in which case the user will be shown a list of available IdPs.
*/
'idp' => NULL,
/* Here you can add other options to the SP. */
),
`default-sp` is the name of the authentication source.
It is used to refer to this authentication source when we use it.
`saml:SP` tells SimpleSAMLphp that authentication with this authentication source is handled by the `saml` module.
The `idp` option should be set to the same value that is set in `default-saml20-idp` in `config.php`.
To ease migration, you probably want the entity ID on the new SP to be different than on the old SP.
This makes it possible to have both the old and the new SP active on the IdP at the same time.
You can also add other options this authentication source.
See the [`saml:SP`](./saml:sp) documentation for more information.
Add the metadata for this authentication source to the IdP
----------------------------------------------------------
After adding the authentication source on the SP, you need to register the metadata on the IdP.
To retrieve the metadata, open the frontpage of your SimpleSAMLphp installation, and go to the federation tab.
You should have a list of metadata entries, and one will be marked with the name of the new authentication source.
In our case, that was `default-sp`.
Click the `Show metadata` link, and you will arrive on a web page with the metadata for that service provider.
How you proceed from here depends on which IdP you are connecting to.
If you use a SimpleSAMLphp IdP, you can use the metadata in the flat file format at the bottom of the page.
That metadata should be added to `saml20-sp-remote.php` on the IdP.
For other IdPs you probably want to use the XML metadata.
Test the new authentication source
----------------------------------
You should now be able to log in using the new authentication source.
Go to the frontpage of your SimpleSAMLphp installation and open the authentication tab.
There you will find a link to test authentication sources.
Click that link, and select the name of your authentication source (`default-sp` in our case).
You should be able to log in using that authentication source, and receive the attributes from the IdP.
Convert the application to use the new API
------------------------------------------
This section will go through some common changes that you need to do when you are using SimpleSAMLphp from a different application.
### `_include.php`
You should also no longer include `.../simplesamlphp/www/_include.php`.
Instead, you should include `.../simplesamlphp/lib/_autoload.php`.
This means that you replace lines like:
require_once('.../simplesamlphp/www/_include.php');
with:
require_once('.../simplesamlphp/lib/_autoload.php');
`_autoload.php` will register an autoloader function for the SimpleSAMLphp classes.
This makes it possible to access the classes from your application.
`_include.php` does the same, but also has some side-effects that you may not want in your application.
If you load any SimpleSAMLphp class files directly, you should remove those lines.
That means that you should remove lines like the following:
require_once('SimpleSAML/Utilities.php');
require_once('SimpleSAML/Session.php');
require_once('SimpleSAML/XHTML/Template.php');
### Authentication API
There is a new authentication API in SimpleSAMLphp which can be used to authenticate against authentication sources.
This API is designed to handle the common operations.
#### Overview
This is a quick overview of the API:
/* Get a reference to our authentication source. */
$as = new \SimpleSAML\Auth\Simple('default-sp');
/* Require the user to be authentcated. */
$as->requireAuth();
/* When that function returns, we have an authenticated user. */
/*
* Retrieve attributes of the user.
*
* Note: If the user isn't authenticated when getAttributes() is
* called, an empty array will be returned.
*/
$attributes = $as->getAttributes();
/* Log the user out. */
$as->logout();
#### `$config` and `$session`
Generally, if you have:
$config = SimpleSAML_Configuration::getInstance();
$session = SimpleSAML_Session::getSessionFromRequest();
you should replace it with this single line:
$as = new \SimpleSAML\Auth\Simple('default-sp');
#### Requiring authentication
Blocks of code like the following:
/* Check if valid local session exists.. */
if (!isset($session) || !$session->isValid('saml2') ) {
SimpleSAML_Utilities::redirect(
'/' . $config->getBaseURL() .
'saml2/sp/initSSO.php',
array('RelayState' => SimpleSAML_Utilities::selfURL())
);
}
should be replaced with a single call to `requireAuth()`:
$as->requireAuth();
#### Fetching attributes
Where you previously called:
$session->getAttributes();
you should now call:
$as->getAttributes();
#### Logging out
Redirecting to the initSLO-script:
SimpleSAML_Utilities::redirect(
'/' . $config->getBaseURL() .
'saml2/sp/initSLO.php',
array('RelayState' => SimpleSAML_Utilities::selfURL())
);
should be replaced with a call to `logout()`:
$as->logout();
If you want to return to a specific URL after logging out, you should include that URL as a parameter to the logout function:
$as->logout('https://example.org/');
Please make sure the URL is trusted. If you obtain the URL from the user input, make sure it is trusted before
calling $as->logout(), by using the SimpleSAML_Utilities::checkURLAllowed() method.
#### Login link
If you have any links to the initSSO-script, those links must be replaced with links to a new script.
The URL to the new script is `https://.../simplesaml/module.php/core/as_login.php`.
It has two mandatory parameters:
* `AuthId`: The id of the authentication source.
* `ReturnTo`: The URL the user should be redirected to after authentication.
#### Logout link
Any links to the initSLO-script must be replaced with links to a new script.
The URL to the new script is `https://.../simplesaml/module.php/core/as_logout.php`.
It has two mandatory parameters:
* `AuthId`: The id of the authentication source.
* `ReturnTo`: The URL the user should be redirected to after logout.
Test the application
--------------------
How you test the application is highly dependent on the application, but here are the elements you should test:
### SP initiated login
Make sure that it is still possible to log into the application.
### IdP initiated login
If you use a SimpleSAMLphp IdP, and you want users to be able to bookmark the login page, you need to test IdP initiated login.
To test IdP initiated login from a SimpleSAMLphp IdP, you can access:
https://.../simplesaml/saml2/idp/SSOService.php?spentityid=&RelayState=
Note that the RelayState parameter is only supported if the IdP runs version 1.5 of SimpleSAMLphp.
If it isn't supported by the IdP, you need to configure the `RelayState` option in the authentication source configuration.
### SP initiated logout
Make sure that logging out of your application also logs out of the IdP.
If this does not work, users who log out of your application can log in again without entering any username or password.
### IdP initiated logout
This is used by the IdP if the user logs out of a different SP connected to the IdP.
In this case, the user should also be logged out of your application.
The easiest way to test this is if you have two SPs connected to the IdP.
You can then log out of one SP and check that you are also logged out of the other.
Remove the old metadata from the IdP
------------------------------------
Once the new SP works correctly, you can remove the metadata for the old SP from the IdP.
How you do that depends on the IdP.
If you are running a SimpleSAMLphp IdP, you can remove the entry for the old SP in `metadata/saml20-sp-remote.php`.
Disable the old SAML 2 SP
-------------------------
You may also want to disable the old SP code in SimpleSAMLphp.
To do that, open `config/config.php`, and change the `enable.saml20-sp` option to `FALSE`.
simplesamlphp-1.15.3/docs/simplesamlphp-metadata-extensions-rpi.md 0000644 0000000 0000000 00000010361 13245225037 024054 0 ustar root root SAML V2.0 Metadata Extensions for Registration and Publication Information
=============================
* Author: Jaime Perez [jaime.perez@uninett.no](mailto:jaime.perez@uninett.no)
This is a reference for the SimpleSAMLphp implementation of the [SAML
V2.0 Metadata Extensions for Registration and Publication Information](http://docs.oasis-open.org/security/saml/Post2.0/saml-metadata-rpi/v1.0/saml-metadata-rpi-v1.0.html)
defined by OASIS.
This extension aims to provide information about the registrars and publishers of the metadata themselves, and it is therefore
available throught different endpoints and modules that provide metadata all along SimpleSAMLphp. More specifically, this
extension can be used for:
- metadata published for a [hosted service provider](./saml:sp).
- metadata published for a [hosted identity provider](./simplesamlphp-reference-idp-hosted).
- metadata collected and published by means of the [`aggregator`](./aggregator:aggregator) or [`aggregator2`](./aggregator2:aggregator2) modules.
Currently, only the `` element is supported.
Depending on the metadata set you want to add this extension to, you will have to configure it on the corresponding
configuration file:
- `metadata/saml20-idp-hosted.php` for hosted identity providers.
- `config/authsources.php` for hosted service providers.
- `config/module_aggregator.php` for the `aggregator` module.
- `config/module_aggregator2.php` for the `aggregator2` module.
RegistrationInfo Items
----------------------
The configuration is the same for all the different files, and consists of a single directive called `RegistrationInfo`, which
**must** be an indexed array with the following options:
`authority`
: A string containing an identifier of the authority who has registered this metadata. This parameter is **mandatory**.
`instant`
: A string containing the instant when the entity or entities where registered by the authority. This parameter is
optional, and must be expressed in the UTC timezone with the *zulu* (`Z`) timezone identifier. If omitted, there will be no
`registrationInstant` in the resulting metadata, except in the `aggregator2` module, which will use the instant when the metadata
was generated.
`policies`
: An indexed array containing URLs pointing to the policy under which the entity or entities where registered. Each
index must be the language code corresponding to the language of the URL. This parameter is optional, and will be omitted in the
resulting metadata if not configured.
Examples
--------
Service Provider:
'default-sp' => array(
'saml:SP',
'entityID' => NULL,
...
'RegistrationInfo' => array(
'authority' => 'urn:mace:sp.example.org',
'instant' => '2008-01-17T11:28:03.577Z',
'policies' => array('en' => 'http://sp.example.org/policy', 'es' => 'http://sp.example.org/politica'),
),
),
Identity Provider:
$metadata['__DYNAMIC:1__'] = array(
'host' => '__DEFAULT__',
...
'RegistrationInfo' => array(
'authority' => 'urn:mace:idp.example.org',
'instant' => '2008-01-17T11:28:03.577Z',
),
);
`aggregator` module:
$config = array(
'aggregators' => array(
...
),
'maxDuration' => 60*60*24*5,
'reconstruct' => FALSE,
...
'RegistrationInfo' => array(
'authority' => 'urn:mace:example.federation',
'instant' => '2008-01-17T11:28:03Z',
'policies' => array('en' => 'http://example.org/federation_policy', 'es' => 'https://example.org/politica_federacion'),
),
);
`aggregator2` module:
$config = array(
'example.org' => array(
'sources' => array(
...
),
'RegistrationInfo' => array(
'authority' => 'urn:mace:example.federation',
'policies' => array('en' => 'http://example.org/federation_policy', 'es' => 'https://example.org/politica_federacion'),
),
),
);
simplesamlphp-1.15.3/docs/simplesamlphp-metadata-extensions-ui.md 0000644 0000000 0000000 00000025524 13245225037 023706 0 ustar root root SAML V2.0 Metadata Extensions for Login and Discovery User Interface
=============================
* Author: Timothy Ace [tace@synacor.com](mailto:tace@synacor.com)
This is a reference for the SimpleSAMLphp implementation of the [SAML
V2.0 Metadata Extensions for Login and Discovery User Interface](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-metadata-ui/v1.0/sstc-saml-metadata-ui-v1.0.pdf)
defined by OASIS.
The metadata extensions are available to both IdP and SP usage of
SimpleSAMLphp. For an IdP, the entries are placed in
`metadata/saml20-idp-hosted.php`, for an SP, they are put inside
the relevant entry in `authsources.php`.
An example for an IdP:
array(
'DisplayName' => array(
'en' => 'English name',
'es' => 'Nombre en Español',
),
'Description' => array(
'en' => 'English description',
'es' => 'Descripción en Español',
),
'InformationURL' => array(
'en' => 'http://example.com/info/en',
'es' => 'http://example.com/info/es',
),
'PrivacyStatementURL' => array(
'en' => 'http://example.com/privacy/en',
'es' => 'http://example.com/privacy/es',
),
'Keywords' => array(
'en' => array('communication', 'federated session'),
'es' => array('comunicación', 'sesión federated'),
),
'Logo' => array(
array(
'url' => 'http://example.com/logo1.png',
'height' => 200,
'width' => 400,
'lang' => 'en',
),
array(
'url' => 'http://example.com/logo2.png',
'height' => 201,
'width' => 401,
),
),
),
'DiscoHints' => array(
'IPHint' => array('130.59.0.0/16', '2001:620::0/96'),
'DomainHint' => array('example.com', 'www.example.com'),
'GeolocationHint' => array('geo:47.37328,8.531126', 'geo:19.34343,12.342514'),
),
/* ... */
);
And for an SP it could look like this:
array(
'saml:SP',
'UIInfo' => array(
'DisplayName' => array(
'en' => 'English name',
'es' => 'Nombre en Español'
),
'Description' => array(
'en' => 'English description',
'es' => 'Descripción en Español
),
),
/* ... */
),
);
The OASIS specification primarily defines how an entity can communicate
metadata related to IdP or service discovery and identification. There
are two different types of
extensions defined. There are the ``elements that define
how an IdP or SP should be displayed and there are the ``
elements that define when an IdP should be chosen/displayed.
UIInfo Items
--------------
These elements are used for IdP and SP discovery to determine what to display
about an IdP or SP. These properties are all children of the `UIInfo` key.
*Note*: Most elements are localized strings that specify the language
using the array key as the language-code:
'DisplayName' => array(
'en' => 'English name',
'es' => 'Nombre en Español',
),
`DisplayName`
: The localized list of names for this entity
'DisplayName' => array(
'en' => 'English name',
'es' => 'Nombre en Español',
),
`Description`
: The localized list of statements used to describe this entity
'Description' => array(
'en' => 'English description',
'es' => 'Descripción en Español',
),
`InformationURL`
: A localized list of URLs where more information about the entity is
located.
'InformationURL' => array(
'en' => 'http://example.com/info/en',
'es' => 'http://example.com/info/es',
),
`PrivacyStatementURL`
: A localized list of URLs where the entity's privacy statement is
located.
'PrivacyStatementURL' => array(
'en' => 'http://example.com/privacy/en',
'es' => 'http://example.com/privacy/es',
),
`Keywords`
: A localized list of keywords used to describe the entity
'Keywords' => array(
'en' => array('communication', 'federated session'),
'es' => array('comunicación', 'sesión federated'),
),
: *Note*: The `+` (plus) character is forbidden by specification from
being part of a Keyword.
`Logo`
: The logos used to represent the entity
'Logo' => array(
array(
'url' => 'http://example.com/logo1.png',
'height' => 200,
'width' => 400,
'lang' => 'en',
),
array(
'url' => 'http://example.com/logo2.png',
'height' => 201,
'width' => 401,
),
),
: An optional `lang` key containing a language-code is supported for
localized logos.
DiscoHints Items
--------------
These elements are only relevant when operating in the IdP role; they
assist IdP discovery to determine when to choose or
present an IdP. These properties are all children of the `DiscoHints`
key.
`IPHint`
: This is a list of both IPv4 and IPv6 addresses in CIDR notation
services by or associated with this entity.
'IPHint' => array('130.59.0.0/16', '2001:620::0/96'),
`DomainHint`
: This specifies a list of domain names serviced by or associated with
this entity.
'DomainHint' => array('example.com', 'www.example.com'),
`GeolocationHint`
: This specifies a list of geographic coordinates associated with, or
serviced by, the entity. Coordinates are given in URI form using the
geo URI scheme [RFC5870](http://www.ietf.org/rfc/rfc5870.txt).
'GeolocationHint' => array('geo:47.37328,8.531126', 'geo:19.34343,12.342514'),
Generated XML Metadata Examples
----------------
If given the following configuration...
$metadata['https://www.example.com/saml/saml2/idp/metadata.php'] = array(
'host' => 'www.example.com',
'certificate' => 'example.com.crt',
'privatekey' => 'example.com.pem',
'auth' => 'example-userpass',
'UIInfo' => array(
'DisplayName' => array(
'en' => 'English name',
'es' => 'Nombre en Español',
),
'Description' => array(
'en' => 'English description',
'es' => 'Descripción en Español',
),
'InformationURL' => array(
'en' => 'http://example.com/info/en',
'es' => 'http://example.com/info/es',
),
'PrivacyStatementURL' => array(
'en' => 'http://example.com/privacy/en',
'es' => 'http://example.com/privacy/es',
),
'Keywords' => array(
'en' => array('communication', 'federated session'),
'es' => array('comunicación', 'sesión federated'),
),
'Logo' => array(
array(
'url' => 'http://example.com/logo1.png',
'height' => 200,
'width' => 400,
),
array(
'url' => 'http://example.com/logo2.png',
'height' => 201,
'width' => 401,
),
),
),
'DiscoHints' => array(
'IPHint' => array('130.59.0.0/16', '2001:620::0/96'),
'DomainHint' => array('example.com', 'www.example.com'),
'GeolocationHint' => array('geo:47.37328,8.531126', 'geo:19.34343,12.342514'),
),
);
... will generate the following XML metadata:
English nameNombre en EspañolEnglish descriptionDescripción en Españolhttp://example.com/info/enhttp://example.com/info/eshttp://example.com/privacy/enhttp://example.com/privacy/escommunication federated+sessioncomunicación sesión+federatedhttp://example.com/logo1.pnghttp://example.com/logo2.png130.59.0.0/162001:620::0/96example.comwww.example.comgeo:47.37328,8.531126geo:19.34343,12.342514
...
simplesamlphp-1.15.3/docs/simplesamlphp-translation.md 0000644 0000000 0000000 00000006564 13245225037 021657 0 ustar root root SimpleSAMLphp Translation Portal
================================================================
## How translated terms are referred from a template
Here is an example of how two terms are included in a template from dictionary files:
t('{core:frontpage:about_header}'); ?>
t('{core:frontpage:about_text}'); ?>
In this example, two translated terms are included: `about_header` and `about_text`. Both these terms are found in a dictionary file named `frontpage`, inside the module named `core`.
**Note:** An important use-case here is that you can create your own module, that includes a new theme that overrides some of the default templates. You may in this template refer to both terms from the existing dictionary files, but you can also add new dictionary files in your new module that may introduce new alternative terms.
## The definition file
When the template library is about to lookup the translation of a term, it will lookup
* the definition file, for the English translation, and
* the translation file, for translation to other languages.
SimpleSAMLphp will always fallback to the English translation using the definition file, both:
* when the term is not translated into the *current selected language*, and
* when the translation file is not available at all.
The name of the definition file is `BASENAME.definition.json`, where the term is referred to like this: `{MODULENAME:BASENAME:TERM}`. The file MUST be placed in the followng location: `modules/MODULENAME/dictionaries/BASENAME.definition.json`.
The content of the defintion file is a *JSON encoded array* of `term => definition`, where definition is an array with an required `en` index for the english translation, and the value is the English text.
Here is an example of a definition file with three terms:
{
"header": {
"en": "Missing cookie"
},
"description": {
"en": "You appear to have disabled cookies in your browser. Please check the settings in your browser, and try again."
},
"retry": {
"en": "Retry"
}
}
Note: you may not include other languages in the definition files, the `en` index is used in order to at a later point in time introduce more meta information for each term, like in example:
"header": {
"en": "Missing cookie",
"_note": "This text shows up on the error page when the browser do not support cookies."
},
To summarize the pattern of the definition file is as follows:
{
"TERM1": {
"en": "English text 1"
},
"TERM2": {
"en": "English text 2"
}
}
## The translation file
The translation file is similar to the definition file, but including translation to languages others than English.
The structure of the file is identical to the definition files, except from the language index, which now is not `en`, but the actual langauge that is translated:
{
"TERM1": {
"no": "Norsk tekst 1",
"da": "Dansk tekst 1"
},
"TERM2": {
"no": "Norsk tekst 2",
"da": "Dansk tekst 2"
}
}
simplesamlphp-1.15.3/docs/simplesamlphp-hok-idp.md 0000644 0000000 0000000 00000007122 13245225037 020643 0 ustar root root Adding Holder-of-Key Web Browser SSO Profile support to the IdP
===============================================================
This document describes the necessary steps to enable support for the [SAML V2.0 Holder-of-Key (HoK) Web Browser SSO Profile](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-holder-of-key-browser-sso.pdf)
on a SimpleSAMLphp Identity Provider (IdP).
The SAML V2.0 HoK Web Browser SSO Profile is an alternate version of the standard SAML Web Browser SSO Profile. Its primary benefit is the enhanced security of the SSO process
while preserving maximum compatibility with existing deployments on client and server side.
When using this profile the communication between the user and the IdP is required to be protected by the TLS protocol. Additionally, the user needs a TLS client certificate.
This certificate is usually selfsigned and stored in the certificate store of the browser or the underlying operating system.
Configuring Apache
------------------
The IdP requests a client certificate from the user agent during the TLS handshake. This behaviour is enabled with the following Apache webserver configuration:
SSLEngine on
SSLCertificateFile /etc/openssl/certs/server.crt
SSLCertificateKeyFile /etc/openssl/private/server.key
SSLVerifyClient optional_no_ca
SSLOptions +ExportCertData
If the user agent can successfully prove possession of the private key associated to the public key from the certificate, the received certificate is stored in the
environment variable `SSL_CLIENT_CERT` of the webserver. The IdP embeds the client certificate into the created HoK assertion.
Enabling HoK SSO Profile on the IdP
-----------------------------------
To enable the IdP to send HoK assertions you must add the `saml20.hok.assertion` option to the `saml20-idp-hosted` metadata file:
$metadata['__DYNAMIC:1__'] = array(
[....]
'auth' => 'example-userpass',
'saml20.hok.assertion' => TRUE,
);
Add new metadata to SPs
-----------------------
After enabling the Holder-of-Key Web Browser SSO Profile your IdP metadata will change. An additional HoK `SingleSignOnService` endpoint is added.
You therefore need to update the metadata for your IdP at your SPs.
The `saml20-idp-remote` metadata for SimpleSAMLphp SPs should contain something like the following code:
'SingleSignOnService' => array (
array (
'hoksso:ProtocolBinding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'Binding' => 'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser',
'Location' => 'https://idp.example.org/simplesaml/saml2/idp/SSOService.php',
),
array (
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'Location' => 'https://idp.example.org/simplesaml/saml2/idp/SSOService.php',
),
),
SP metadata on the IdP
----------------------
A SP using the HoK Web Browser SSO Profile must have an `AssertionConsumerService` endpoint supporting that profile.
This means that you have to use the complex endpoint format in `saml20-sp-remote` metadata.
In general, this should look like the following code:
'AssertionConsumerService' => array (
array(
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
'Location' => 'https://sp.example.org/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp',
'index' => 0,
),
array(
'Binding' => 'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser',
'Location' => 'https://sp.example.org/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp',
'index' => 4,
),
),
(The specific values of the various fields will vary depending on the SP.)
simplesamlphp-1.15.3/docs/simplesamlphp-artifact-idp.md 0000644 0000000 0000000 00000007321 13245225037 021660 0 ustar root root Adding HTTP-Artifact support to the IdP
=======================================
This document describes the necessary steps to enable support for the HTTP-Artifact binding on a SimpleSAMLphp IdP:
1. Configure SimpleSAMLphp to use memcache to store the session.
2. Enable support for sending artifacts in `saml20-idp-hosted`.
3. Add the webserver certificate to the generated metadata.
Memcache
--------
To enable memcache, you must first install and configure memcache on the server hosting your IdP.
You need both a memcache server and a the PHP memcached client (extension).
How this is done depends on the distribution.
If you are running Debian or Ubuntu, you can install this by running:
apt install memcached php-memcached
simpleSAMLphp also supports the legacy `php-memcache` (without `d`) variant.
*Note*: For security, you must make sure that the memcache server is inaccessible to other hosts.
The default configuration on Debian is for the memcache server to be accessible to only the local host.
Once the memcache server is configured, you can configure simplesamlphp to use it to store sessions.
You can do this by setting the `session.handler` option in `config.php` to `memcache`.
If you are running memcache on a different server than the IdP, you must also change the `memcache_store.servers` option in `config.php`.
Enabling artifact on the IdP
----------------------------
To enable the IdP to send artifacts, you must add the `saml20.sendartifact` option to the `saml20-idp-hosted` metadata file:
$metadata['__DYNAMIC:1__'] = array(
[....]
'auth' => 'example-userpass',
'saml20.sendartifact' => TRUE,
);
Add new metadata to SPs
-----------------------
After enabling the Artifact binding, your IdP metadata will change to add a ArtifactResolutionService endpoint.
You therefore need to update the metadata for your IdP at your SPs.
`saml20-idp-remote` metadata for SimpleSAMLphp SPs should contain something like:
'ArtifactResolutionService' => array(
array(
'index' => 0,
'Location' => 'https://idp.example.org/simplesaml/saml2/idp/ArtifactResolutionService.php',
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP',
),
),
SP metadata on the IdP
----------------------
An SP using the HTTP-Artifact binding must have an AssertionConsumerService endpoint supporting that binding.
This means that you must use the complex endpoint format in `saml20-sp-remote` metadata.
In general, that should look something like:
'AssertionConsumerService' => array (
array(
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
'Location' => 'https://sp.example.org/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp',
'index' => 0,
),
array(
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact',
'Location' => 'https://sp.example.org/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp',
'index' => 2,
),
),
(The specific values of the various fields will vary depending on the SP.)
Certificate in metadata
-----------------------
Some SPs validates the SSL certificate on the ArtifactResolutionService using the certificates in the metadata.
You may therefore have to add the webserver certificate to the metadata that your IdP generates.
To do this, you need to set the `https.certificate` option in the `saml20-idp-hosted` metadata file.
That option should refer to a file containing the webserver certificate.
$metadata['__DYNAMIC:1__'] = array(
[....]
'auth' => 'example-userpass',
'saml20.sendartifact' => TRUE,
'https.certificate' => '/etc/apache2/webserver.crt',
);
simplesamlphp-1.15.3/docs/simplesamlphp-customauth.md 0000644 0000000 0000000 00000033117 13245225037 021507 0 ustar root root Implementing custom username/password authentication
====================================================
This is a step-by-step guide for creating a custom username/password [authentication source](./simplesamlphp-authsource) for SimpleSAMLphp.
An authentication source is responsible for authenticating the user, typically by getting a username and password, and looking it up in some sort of database.
Create a custom module
----------------------
All custom code for SimpleSAMLphp should be contained in a [module](./simplesamlphp-modules).
This ensures that you can upgrade your SimpleSAMLphp installation without overwriting your own code.
In this example, we will call the module `mymodule`.
It will be located under `modules/mymodule`.
First we need to create the module directory:
cd modules
mkdir mymodule
Since this is a custom module, it should always be enabled.
Therefore we create a `default-enable` file in the module.
We do that by copying the `default-enable` file from the `core` module.
cd mymodule
cp ../core/default-enable .
Now that we have our own module, we can move on to creating an authentication source.
Creating a basic authentication source
--------------------------------------
Authentication sources are implemented using PHP classes.
We are going to create an authentication source named `mymodule:MyAuth`.
It will be implemented in the file `modules/mymodule/lib/Auth/Source/MyAuth.php`.
To begin with, we will create a very simple authentication source, where the username and password is hardcoded into the source code.
Create the file `modules/mymodule/lib/Auth/Source/MyAuth.php` with the following contents:
array('theusername'),
'displayName' => array('Some Random User'),
'eduPersonAffiliation' => array('member', 'employee'),
);
}
}
Some things to note:
- The classname is `sspmod_mymodule_Auth_Source_MyAuth`.
This tells SimpleSAMLphp to look for the class in `modules/mymodule/lib/Auth/Source/MyAuth.php`.
- Our authentication source subclassese `sspmod_core_Auth_UserPassBase`.
This is a helper-class that implements much of the common code needed for username/password authentication.
- The `login` function receives the username and password the user enters.
It is expected to authenticate the user.
If the username or password is correct, it must return a set of attributes for the user.
Otherwise, it must throw the `SimpleSAML_Error_Error('WRONGUSERPASS');` exception.
- Attributes are returned as an associative array of `name => values` pairs.
All attributes can have multiple values, so the values are always stored in an array.
Configuring our authentication source
-------------------------------------
Before we can test our authentication source, we must add an entry for it in `config/authsources.php`.
`config/authsources.php` contains an list of enabled authentication sources.
The entry looks like this:
'myauthinstance' => array(
'mymodule:MyAuth',
),
You can add it to the beginning of the list, so that the file looks something like this:
array(
'mymodule:MyAuth',
),
/* Other authentication sources follow. */
);
`myauthinstance` is the name of this instance of the authentication source.
(You are allowed to have multiple instances of an authentication source with different configuration.)
The instance name is used to refer to this authentication source in other configuration files.
The first element of the configuration of the authentication source must be `'mymodule:MyAuth'`.
This tells SimpleSAMLphp to look for the `sspmod_mymodule_Auth_Source_MyAuth` class.
Testing our authentication source
---------------------------------
Now that we have configured the authentication source, we can test it by accessing "authentication"-page of the SimpleSAMLphp web interface.
By default, the web interface can be found on `http://yourhostname.com/simplesaml/`.
(Obviously, "yourhostname.com" should be replaced with your real hostname.)
Then select the "Authentication"-tab, and choose "Test configured authentication sources".
You should then receive a list of authentication sources from `config/authsources.php`.
Select `myauthinstance`, and log in using "theusername" as the username, and "thepassword" as the password.
You should then arrive on a page listing the attributes we return from the `login` function.
Next, you should log out by following the log out link.
Using our authentication source in an IdP
-----------------------------------------
To use our new authentication source in an IdP we just need to update the IdP configuration to use it.
Open `metadata/saml20-idp-hosted.php`.
In that file you should locate the `auth`-option for your IdP, and change it to `myauthinstance`:
'myauthinstance',
/* ... */
);
You can then test logging in to the IdP.
If you have logged in previously, you may need to log out first.
Adding configuration to our authentication source
-------------------------------------------------
Instead of hardcoding options in our authentication source, they should be configurable.
We are now going to extend our authentication source to allow us to configure the username and password in `config/authsources.php`.
First, we need to define the properties in the class that should hold our configuration:
private $username;
private $password;
Next, we create a constructor for the class.
The constructor is responsible for parsing the configuration and storing it in the properties.
public function __construct($info, $config) {
parent::__construct($info, $config);
if (!is_string($config['username'])) {
throw new Exception('Missing or invalid username option in config.');
}
$this->username = $config['username'];
if (!is_string($config['password'])) {
throw new Exception('Missing or invalid password option in config.');
}
$this->password = $config['password'];
}
We can then use the properties in the `login` function.
The complete class file should look like this:
username = $config['username'];
if (!is_string($config['password'])) {
throw new Exception('Missing or invalid password option in config.');
}
$this->password = $config['password'];
}
protected function login($username, $password) {
if ($username !== $this->username || $password !== $this->password) {
throw new SimpleSAML_Error_Error('WRONGUSERPASS');
}
return array(
'uid' => array($this->username),
'displayName' => array('Some Random User'),
'eduPersonAffiliation' => array('member', 'employee'),
);
}
}
We can then update our entry in `config/authsources.php` with the configuration options:
'myauthinstance' => array(
'mymodule:MyAuth',
'username' => 'theconfigusername',
'password' => 'theconfigpassword',
),
Next, you should go to the "Test configured authentication sources" page again, and test logging in.
Note that we have updated the username & password to "theconfigusername" and "theconfigpassword".
(You may need to log out first before you can log in again.)
A more complete example - custom database authentication
--------------------------------------------------------
The [sqlauth:SQL](./sqlauth:sql) authentication source can do simple authentication against SQL databases.
However, in some cases it cannot be used, for example because the database layout is too complex, or because the password validation routines cannot be implemented in SQL.
What follows is an example of an authentication source that fetches an user from a database, and validates the password using a custom function.
This code assumes that the database contains a table that looks like this:
CREATE TABLE userdb (
username VARCHAR(32) PRIMARY KEY NOT NULL,
password_hash VARCHAR(64) NOT NULL,
full_name TEXT NOT NULL);
An example user (with password "secret"):
INSERT INTO userdb (username, password_hash, full_name)
VALUES('exampleuser', 'QwVYkvlrAMsXIgULyQ/pDDwDI3dF2aJD4XeVxg==', 'Example User');
In this example, the `password_hash` contains a base64 encoded SSHA password.
A SSHA password is created like this:
$password = 'secret';
$numSalt = 8; /* Number of bytes with salt. */
$salt = '';
for ($i = 0; $i < $numSalt; $i++) {
$salt .= chr(mt_rand(0, 255));
}
$digest = sha1($password . $salt, TRUE);
$password_hash = base64_encode($digest . $salt);
The class follows:
dsn = $config['dsn'];
if (!is_string($config['username'])) {
throw new Exception('Missing or invalid username option in config.');
}
$this->username = $config['username'];
if (!is_string($config['password'])) {
throw new Exception('Missing or invalid password option in config.');
}
$this->password = $config['password'];
}
/**
* A helper function for validating a password hash.
*
* In this example we check a SSHA-password, where the database
* contains a base64 encoded byte string, where the first 20 bytes
* from the byte string is the SHA1 sum, and the remaining bytes is
* the salt.
*/
private function checkPassword($passwordHash, $password) {
$passwordHash = base64_decode($passwordHash);
$digest = substr($passwordHash, 0, 20);
$salt = substr($passwordHash, 20);
$checkDigest = sha1($password . $salt, TRUE);
return $digest === $checkDigest;
}
protected function login($username, $password) {
/* Connect to the database. */
$db = new PDO($this->dsn, $this->username, $this->password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
/* Ensure that we are operating with UTF-8 encoding.
* This command is for MySQL. Other databases may need different commands.
*/
$db->exec("SET NAMES 'utf8'");
/* With PDO we use prepared statements. This saves us from having to escape
* the username in the database query.
*/
$st = $db->prepare('SELECT username, password_hash, full_name FROM userdb WHERE username=:username');
if (!$st->execute(array('username' => $username))) {
throw new Exception('Failed to query database for user.');
}
/* Retrieve the row from the database. */
$row = $st->fetch(PDO::FETCH_ASSOC);
if (!$row) {
/* User not found. */
SimpleSAML\Logger::warning('MyAuth: Could not find user ' . var_export($username, TRUE) . '.');
throw new SimpleSAML_Error_Error('WRONGUSERPASS');
}
/* Check the password. */
if (!$this->checkPassword($row['password_hash'], $password)) {
/* Invalid password. */
SimpleSAML\Logger::warning('MyAuth: Wrong password for user ' . var_export($username, TRUE) . '.');
throw new SimpleSAML_Error_Error('WRONGUSERPASS');
}
/* Create the attribute array of the user. */
$attributes = array(
'uid' => array($username),
'displayName' => array($row['full_name']),
'eduPersonAffiliation' => array('member', 'employee'),
);
/* Return the attributes. */
return $attributes;
}
}
And configured in `config/authsources.php`:
'myauthinstance' => array(
'mymodule:MyAuth',
'dsn' => 'mysql:host=sql.example.org;dbname=userdatabase',
'username' => 'db_username',
'password' => 'secret_db_password',
),
simplesamlphp-1.15.3/docs/simplesamlphp-sp-api.md 0000644 0000000 0000000 00000016114 13245225037 020502 0 ustar root root SimpleSAMLphp SP API reference
==============================
This document describes the \SimpleSAML\Auth\Simple API.
This is the preferred API for integrating SimpleSAMLphp with other applications.
Constructor
-----------
new \SimpleSAML\Auth\Simple(string $authSource)
The constructor initializes a \SimpleSAML\Auth\Simple object.
### Parameters
It has a single parameter, which is the ID of the authentication source that should be used.
This authentication source must exist in `config/authsources.php`.
### Example
$auth = new \SimpleSAML\Auth\Simple('default-sp');
`isAuthenticated`
-----------------
bool isAuthenticated()
Check whether the user is authenticated with this authentication source.
`TRUE` is returned if the user is authenticated, `FALSE` if not.
### Example
if (!$auth->isAuthenticated()) {
/* Show login link. */
print('Login');
}
`requireAuth`
-------------
void requireAuth(array $params = array())
Make sure that the user is authenticated.
This function will only return if the user is authenticated.
If the user isn't authenticated, this function will start the authentication process.
### Parameters
`$params` is an associative array with named parameters for this function.
See the documentation for the `login`-function for a description of the parameters.
### Example 1
$auth->requireAuth();
print("Hello, authenticated user!");
### Example 2
/*
* Return the user to the frontpage after authentication, don't post
* the current POST data.
*/
$auth->requireAuth(array(
'ReturnTo' => 'https://sp.example.org/',
'KeepPost' => FALSE,
));
print("Hello, authenticated user!");
`login`
-------------
void login(array $params = array())
Start a login operation.
This function will always start a new authentication process.
### Parameters
The following global parameters are supported:
`ErrorURL` (`string`)
: A URL to a page which will receive errors that may occur during authentication.
`KeepPost` (`bool`)
: If set to `TRUE`, the current POST data will be submitted again after authentication.
The default is `TRUE`.
`ReturnTo` (`string`)
: The URL the user should be returned to after authentication.
The default is to return the user to the current page.
`ReturnCallback` (`array`)
: The function we should call when the user finishes authentication.
The [`saml:SP`](./saml:sp) authentication source also defines some parameters.
### Example
# Send a passive authentication request.
$auth->login(array(
'isPassive' => TRUE,
'ErrorURL' => 'https://.../error_handler.php',
));
`logout`
--------
void logout(mixed $params = NULL)
Log the user out.
After logging out, the user will either be redirected to another page, or a function will be called.
This function never returns.
### Parameters
`$params`
: Parameters for the logout operation.
This can either be a simple string, in which case it is interpreted as the URL the user should be redirected to after logout, or an associative array with logout parameters.
If this parameter isn't specified, we will redirect the user to the current URL after logout.
If the parameter is an an array, it can have the following options:
- `ReturnTo`: The URL the user should be returned to after logout.
- `ReturnCallback`: The function that should be called after logout.
- `ReturnStateParam`: The parameter we should return the state in when redirecting.
- `ReturnStateStage`: The stage the state array should be saved with.
The `ReturnState` parameters allow access to the result of the logout operation after it completes.
### Example 1
Logout, and redirect to the specified URL.
$auth->logout('https://sp.example.org/logged_out.php');
### Example 2
Same as the previous, but check the result of the logout operation afterwards.
$auth->logout(array(
'ReturnTo' => 'https://sp.example.org/logged_out.php',
'ReturnStateParam' => 'LogoutState',
'ReturnStateStage' => 'MyLogoutState',
));
And in logged_out.php:
$state = SimpleSAML_Auth_State::loadState((string)$_REQUEST['LogoutState'], 'MyLogoutState');
$ls = $state['saml:sp:LogoutStatus']; /* Only works for SAML SP */
if ($ls['Code'] === 'urn:oasis:names:tc:SAML:2.0:status:Success' && !isset($ls['SubCode'])) {
/* Successful logout. */
echo("You have been logged out.");
} else {
/* Logout failed. Tell the user to close the browser. */
echo("We were unable to log you out of all your sessions. To be completely sure that you are logged out, you need to close your web browser.");
}
`getAttributes`
---------------
array getAttributes()
Retrieve the attributes of the current user.
If the user isn't authenticated, an empty array will be returned.
The attributes will be returned as an associative array with the name of the attribute as the key and the value as an array of one or more strings:
array(
'uid' => array('testuser'),
'eduPersonAffiliation' => array('student', 'member'),
)
### Example
$attrs = $auth->getAttributes();
if (!isset($attrs['displayName'][0])) {
throw new Exception('displayName attribute missing.');
}
$name = $attrs['displayName'][0];
print('Hello, ' . htmlspecialchars($name));
`getAuthData`
---------------
mixed getAuthData(string $name)
Retrieve the specified authentication data for the current session.
NULL is returned if the user isn't authenticated.
The available authentication data depends on the module used for authentication.
See the [`saml:SP`](./saml:sp) reference for information about available SAML authentication data.
### Example
$idp = $auth->getAuthData('saml:sp:IdP');
print('You are logged in from: ' . htmlspecialchars($idp));
`getLoginURL`
-------------
string getLoginURL(string $returnTo = NULL)
Retrieve a URL that can be used to start authentication.
### Parameters
`$returnTo`
: The URL the user should be returned to after authentication.
The default is the current page.
### Example
$url = $auth->getLoginURL();
print('Login');
### Note
The URL returned by this function is static, and will not change.
You can easily create your own links without using this function.
The URL should be:
.../simplesaml/module.php/core/as_login.php?AuthId=&ReturnTo=
`getLogoutURL`
--------------
string getLogoutURL(string $returnTo = NULL)
Retrieve a URL that can be used to trigger logout.
### Parameters
`$returnTo`
: The URL the user should be returned to after logout.
The default is the current page.
### Example
$url = $auth->getLogoutURL();
print('Logout');
### Note
The URL returned by this function is static, and will not change.
You can easily create your own links without using this function.
The URL should be:
.../simplesaml/module.php/core/as_logout.php?AuthId=&ReturnTo=
simplesamlphp-1.15.3/docs/simplesamlphp-database.md 0000644 0000000 0000000 00000010131 13245225037 021046 0 ustar root root SimpleSAML\Database
=============================
Purpose
-------
This document covers the SimpleSAML\Database class and is only relevant to anyone writing code for SimpleSAMLphp, including modules, that require a database connection.
The Database class provides a single class that can be used to connect to a database which can be shared by anything within SimpleSAMLphp.
Getting Started
---------------
If you are just using the already configured database, which would normally be the case, all you need to do is get the global instance of the Database class.
$db = SimpleSAML\Database::getInstance();
If there is a requirement to connect to an alternate database server (ex. authenticating users that exist on a different SQL server or database) you can specify an alternate configuration.
$config = new SimpleSAML_Configuration($myconfigarray, "mymodule/lib/Auth/Source/myauth.php");
$db = SimpleSAML\Database::getInstance($config);
That will create a new instance of the database, separate from the global instance, specific to the configuration defined in $myconfigarray. If you are going to specify an alternate config, your configuration array must contain the same keys that exist in the master config (database.dsn, database.username, database.password, database.prefix, etc).
Database Prefix
---------------
Administrators can add a prefix to all the table names that this database classes accesses and you should take that in account when querying. Assuming that a prefix has been configured as "sp_":
$table = $db->applyPrefix("saml20_idp_hosted");
$table would be set to "sp_saml20_idp_hosted"
Querying The Database
---------------------
You can query the database through two public functions read() and write() which are fairly self-explanitory when it comes to determining which one to use when querying.
### Writing to The Database
Since the database class allows administrators to configure master and slave database servers, the write function will always use the master database connection.
The write function takes 2 parameters: SQL, params.
$table = $db->applyPrefix("test");
$values = array(
'id' => 20,
'data' => 'Some data',
);
$query = $db->write("INSERT INTO $table (id, data) VALUES (:id, :data)", $values);
The values specified in the $values array will be bound to the placeholders and will be executed on the master. By default, values are binded as PDO::PARAM_STR. If you need to override this, you can specify it in the values array.
$table = $db->applyPrefix("test");
$values = array(
'id' => array(20, PDO::PARAM_INT),
'data' => 'Some data',
);
$query = $db->write("INSERT INTO $table (id, data) VALUES (:id, :data)", $values);
You can also skip usage of prepared statements. You should **only** use this if you have a statement that has no user input (ex. CREATE TABLE). If the params variable is explicity set to false, it will skip usage of prepared statements. This is only available when writing to the database.
$table = $db->applyPrefix("test");
$query = $db->write("CREATE TABLE IF NOT EXISTS $table (id INT(16) NOT NULL, data TEXT NOT NULL)", false);
### Reading The Database
Since the database class allows administrators to configure master and slave database servers, the read function will randomly select a slave server to query. If no slaves are configured, it will read from the master.
The read function takes 2 parameters: SQL, params.
$table = $db->applyPrefix("test");
$values = array(
'id' => 20,
);
$query = $db->read("SELECT * FROM $table WHERE id = :id", $values);
The values specified in the $values array will be bound to the placeholders and will be executed on the selected slave. By default, values are binded as PDO::PARAM_STR. If you need to override this, you can specify it in the values array.
$table = $db->applyPrefix("test");
$values = array(
'id' => array(20, PDO::PARAM_INT),
);
$query = $db->read("SELECT * FROM $table WHERE id = :id", $values);
simplesamlphp-1.15.3/docs/simplesamlphp-reference-sp-remote.md 0000644 0000000 0000000 00000040301 13245225037 023153 0 ustar root root SP remote metadata reference
============================
This is a reference for metadata options available for
`metadata/saml20-sp-remote.php` and `metadata/shib13-sp-remote.php`.
Both files have the following format:
array(
'en' => 'A service',
'no' => 'En tjeneste',
),
`OrganizationName`
: The name of the organization responsible for this SPP.
This name does not need to be suitable for display to end users.
: This option can be translated into multiple languages by specifying the value as an array of language-code to translated name:
'OrganizationName' => array(
'en' => 'Example organization',
'no' => 'Eksempel organisation',
),
: *Note*: If you specify this option, you must also specify the `OrganizationURL` option.
`OrganizationDisplayName`
: The name of the organization responsible for this IdP.
This name must be suitable for display to end users.
If this option isn't specified, `OrganizationName` will be used instead.
: This option can be translated into multiple languages by specifying the value as an array of language-code to translated name.
: *Note*: If you specify this option, you must also specify the `OrganizationName` option.
`OrganizationURL`
: A URL the end user can access for more information about the organization.
: This option can be translated into multiple languages by specifying the value as an array of language-code to translated URL.
: *Note*: If you specify this option, you must also specify the `OrganizationName` option.
`privacypolicy`
: This is an absolute URL for where an user can find a privacypolicy
for this SP. If set, this will be shown on the consent page.
`%SPENTITYID%` in the URL will be replaced with the entity id of
this service provider.
: Note that this option also exists in the IdP-hosted metadata. This
entry in the SP-remote metadata overrides the option in the
IdP-hosted metadata.
`userid.attribute`
: The attribute name of an attribute which uniquely identifies
the user. This attribute is used if SimpleSAMLphp needs to generate
a persistent unique identifier for the user. This option can be set
in both the IdP-hosted and the SP-remote metadata. The value in the
sp-remote metadata has the highest priority. The default value is
`eduPersonPrincipalName`.
: Note that this option also exists in the IdP-hosted metadata. This
entry in the SP-remote metadata overrides the option in the
IdP-hosted metadata.
SAML 2.0 options
----------------
The following SAML 2.0 options are available:
`AssertionConsumerService`
: The URL of the AssertionConsumerService endpoint for this SP.
This option is required - without it you will not be able to send
responses back to the SP.
: The value of this option is specified in one of several [endpoint formats](./simplesamlphp-metadata-endpoints).
`attributes.NameFormat`
: What value will be set in the Format field of attribute
statements. This parameter can be configured multiple places, and
the actual value used is fetched from metadata by the following
priority:
: 1. SP Remote Metadata
2. IdP Hosted Metadata
: The default value is:
`urn:oasis:names:tc:SAML:2.0:attrname-format:basic`
: Some examples of values specified in the SAML 2.0 Core
Specification:
: - `urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified`
- `urn:oasis:names:tc:SAML:2.0:attrname-format:uri` (The default
in Shibboleth 2.0)
- `urn:oasis:names:tc:SAML:2.0:attrname-format:basic` (The
default in Sun Access Manager)
: You can also define your own value.
: Note that this option also exists in the IdP-hosted metadata. This
entry in the SP-remote metadata overrides the option in the
IdP-hosted metadata.
: (This option was previously named `AttributeNameFormat`.)
`encryption.blacklisted-algorithms`
: Blacklisted encryption algorithms. This is an array containing the algorithm identifiers.
: Note that this option also exists in the IdP-hosted metadata. This
entry in the SP-remote metadata overrides the option in the
[IdP-hosted metadata](./simplesamlphp-reference-idp-hosted).
: The RSA encryption algorithm with PKCS#1 v1.5 padding is blacklisted by default for security reasons. Any assertions
encrypted with this algorithm will therefore fail to decrypt. You can override this limitation by defining an empty
array in this option (or blacklisting any other algorithms not including that one). However, it is strongly
discouraged to do so. For your own safety, please include the string 'http://www.w3.org/2001/04/xmlenc#rsa-1_5' if
you make use of this option.
`ForceAuthn`
: Set this `TRUE` to force the user to reauthenticate when the IdP
receives authentication requests from this SP. The default is
`FALSE`.
`NameIDFormat`
: The `NameIDFormat` this SP should receive. The three most commonly
used values are:
: 1. `urn:oasis:names:tc:SAML:2.0:nameid-format:transient`
2. `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent`
3. `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`
: The `transient` format will generate a new unique ID every time
the SP logs in.
: To properly support the `persistent` and `emailAddress` formats,
you should configure [NameID generation filters](./saml:nameid)
on your IdP.
`nameid.encryption`
: Whether NameIDs sent to this SP should be encrypted. The default
value is `FALSE`.
: Note that this option also exists in the IdP-hosted metadata. This
entry in the SP-remote metadata overrides the option in the
[IdP-hosted metadata](./simplesamlphp-reference-idp-hosted).
`SingleLogoutService`
: The URL of the SingleLogoutService endpoint for this SP.
This option is required if you want to implement single logout for
this SP. If the option isn't specified, this SP will not be logged
out automatically when a single logout operation is initialized.
: The value of this option is specified in one of several [endpoint formats](./simplesamlphp-metadata-endpoints).
`SingleLogoutServiceResponse`
: The URL logout responses to this SP should be sent. If this option
is unspecified, the `SingleLogoutService` endpoint will be used as
the recipient of logout responses.
`SPNameQualifier`
: SP NameQualifier for this SP. If not set, the IdP will set the
SPNameQualifier to be the SP entity ID.
`certData`
: The base64 encoded certificate for this SP. This is an alternative to storing the certificate in a file on disk and specifying the filename in the `certificate`-option.
`certificate`
: Name of certificate file for this SP. The certificate is used to
verify the signature of messages received from the SP (if
`redirect.validate`is set to `TRUE`), and to encrypting assertions
(if `assertion.encryption` is set to TRUE and `sharedkey` is
unset.)
`saml20.sign.response`
: Whether `` messages should be signed.
Defaults to `TRUE`.
: Note that this option also exists in the IdP-hosted metadata.
The value in the SP-remote metadata overrides the value in the IdP-hosted metadata.
`saml20.sign.assertion`
: Whether `` elements should be signed.
Defaults to `TRUE`.
: Note that this option also exists in the IdP-hosted metadata.
The value in the SP-remote metadata overrides the value in the IdP-hosted metadata.
`signature.algorithm`
: The algorithm to use when signing any message sent to this specific service provider. Defaults to RSA-SHA1.
: Note that this option also exists in the IdP-hosted metadata.
The value in the SP-remote metadata overrides the value in the IdP-hosted metadata.
: Possible values:
* `http://www.w3.org/2000/09/xmldsig#rsa-sha1`
*Note*: the use of SHA1 is **deprecated** and will be disallowed in the future.
* `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`
`signature.privatekey`
: Name of private key file for this IdP, in PEM format. The filename is relative to the cert/-directory.
: Note that this option also exists in the IdP-hosted metadata. This entry in the SP-remote metadata overrides the option `privatekey` in the IdP-hosted metadata.
`signature.privatekey_pass`
: Passphrase for the private key. Leave this option out if the private key is unencrypted.
: Note that this option only is used if `signature.privatekey` is present.
`signature.certificate`
: Certificate file included by IdP for KeyInfo within the signature for the SP, in PEM format. The filename is relative to the cert/-directory.
: If `signature.privatekey` is present and `signature.certificate` is left blank, X509Certificate will not be included with the signature.
`simplesaml.nameidattribute`
: When the value of the `NameIDFormat`-option is set to either
`email` or `persistent`, this is the name of the attribute which
should be used as the value of the `NameID`. The attribute must
be in the set of attributes exported to the SP (that is, be in
the `attributes` array). For more advanced control over `NameID`,
including the ability to specify any attribute regardless of
the set sent to the SP, see the [NameID processing filters](./saml:nameid).
: Typical values can be `mail` for when using the `email` format,
and `eduPersonTargetedID` when using the `persistent` format.
`simplesaml.attributes`
: Whether the SP should receive any attributes from the IdP. The
default value is `TRUE`.
`attributeencodings`
: What encoding should be used for the different attributes. This is
an array which maps attribute names to attribute encodings. There
are three different encodings:
: - `string`: Will include the attribute as a normal string. This is
the default.
: - `base64`: Store the attribute as a base64 encoded string. This
is the default when the `base64attributes`-option is set to
`TRUE`.
: - `raw`: Store the attribute without any modifications. This
makes it possible to include raw XML in the response.
`sign.logout`
: Whether to sign logout messages sent to this SP.
: Note that this option also exists in the IdP-hosted metadata.
The value in the SP-remote metadata overrides the value in the IdP-hosted metadata.
`validate.authnrequest`
: Whether we require signatures on authentication requests sent from this SP.
: Note that this option also exists in the IdP-hosted metadata.
The value in the SP-remote metadata overrides the value in the IdP-hosted metadata.
`validate.logout`
: Whether we require signatures on logout messages sent from this SP.
: Note that this option also exists in the IdP-hosted metadata.
The value in the SP-remote metadata overrides the value in the IdP-hosted metadata.
### Encrypting assertions
It is possible to encrypt the assertions sent to a SP. Currently the
only algorithm supported is `AES128_CBC` or `RIJNDAEL_128`.
There are two modes of encryption supported by SimpleSAMLphp. One is
symmetric encryption, in which case both the SP and the IdP needs to
share a key. The other mode is the use of public key encryption. In
that mode, the public key of the SP is extracted from the certificate
of the SP.
`assertion.encryption`
: Whether assertions sent to this SP should be encrypted. The default
value is `FALSE`.
: Note that this option also exists in the IdP-hosted metadata. This
entry in the SP-remote metadata overrides the option in the
IdP-hosted metadata.
`sharedkey`
: Symmetric key which should be used for encryption. This should be a
128-bit key. If this option is not specified, public key encryption
will be used instead.
### Fields for signing and validating messages
SimpleSAMLphp only signs authentication responses by default.
Signing of logout requests and logout responses can be enabled by
setting the `redirect.sign` option. Validation of received messages
can be enabled by the `redirect.validate` option.
These options overrides the options set in `saml20-idp-hosted`.
`redirect.sign`
: Whether logout requests and logout responses sent to this SP should
be signed. The default is `FALSE`.
`redirect.validate`
: Whether authentication requests, logout requests and logout
responses received from this SP should be validated. The default is
`FALSE`
**Example: Configuration for validating messages**
'redirect.validate' => TRUE,
'certificate' => 'example.org.crt',
### Fields for scoping
Only relevant if you are a proxy/bridge and wants to limit the idps this
sp can use.
`IDPList`
: The list of scoped idps ie. the list of entityids for idps that are
relevant for this sp. The final list is the concatenation of the list
given as parameter to InitSSO (at the sp), the list configured at the
sp and the list configured at the ipd (here) for this sp. The intersection
of the final list and the idps configured at the at this idp will be
presented to the user at the discovery service if neccessary. If only one
idp is in the intersection the discoveryservice will go directly to the idp.
**Example: Configuration for scoping**
'IDPList' => array('https://idp1.wayf.dk', 'https://idp2.wayf.dk'),
Shibboleth 1.3 options
----------------------
The following options for Shibboleth 1.3 SP's are avaiblable:
`AssertionConsumerService`
: The URL of the AssertionConsumerService endpoint for this SP.
This endpoint must accept the SAML responses encoded with the
`urn:oasis:names:tc:SAML:1.0:profiles:browser-post` encoding.
This option is required - without it you will not be able to send
responses back to the SP.
: The value of this option is specified in one of several [endpoint formats](./simplesamlphp-metadata-endpoints).
`NameQualifier`
: What the value of the `NameQualifier`-attribute of the
``-element should be. The default value is the
entity ID of the SP.
`audience`
: The value which should be given in the ``-element in the
``-element in the response. The
default value is the entity ID of the SP.
`scopedattributes`
: Array with names of attributes which should be scoped. Scoped
attributes will receive a `Scope`-attribute on the
`AttributeValue`-element. The value of the Scope-attribute will
be taken from the attribute value:
: `someuser@example.org`
: will be transformed into
: `someuser`
: By default, no attributes are scoped. This option overrides the
option with the same name in the `shib13-idp-hosted.php` metadata
file.
simplesamlphp-1.15.3/docs/simplesamlphp-googleapps.md 0000644 0000000 0000000 00000024535 13245225037 021457 0 ustar root root Setting up a SimpleSAMLphp SAML 2.0 IdP to use with Google Apps / G Suite for Education
============================================
SimpleSAMLphp news and documentation
------------------------------------
This document is part of the SimpleSAMLphp documentation suite.
* [List of all SimpleSAMLphp documentation](https://simplesamlphp.org/docs)
* [SimpleSAMLphp homepage](https://simplesamlphp.org)
## Introduction
This article assumes that you have already read the SimpleSAMLphp installation manual, and installed a version of SimpleSAMLphp at your
server.
In this example we will setup this server as an IdP for Google Apps for Education:
dev2.andreas.feide.no
## Enabling the Identity Provider functionality
Edit `config.php`, and enable the SAML 2.0 IdP:
'enable.saml20-idp' => true,
'enable.shib13-idp' => false,
## Setting up a signing certificate
You must generate a certificate for your IdP.
Here is an example of an openssl command to generate a new key and a self signed certificate to use for signing SAML messages:
openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes -out googleappsidp.crt -keyout googleappsidp.pem
The certificate above will be valid for 10 years.
Here is an example of typical user input when creating a certificate request:
Country Name (2 letter code) [AU]:NO
State or Province Name (full name) [Some-State]:Trondheim
Locality Name (eg, city) []:Trondheim
Organization Name (eg, company) [Internet Widgits Pty Ltd]:UNINETT
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:dev2.andreas.feide.no
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
**Note**: SimpleSAMLphp will only work with RSA and not DSA certificates.
Authentication source
---------------------
The next step is to configure the way users authenticate on your IdP. Various modules in the `modules/` directory provides methods for authenticating your users. This is an overview of those that are included in the SimpleSAMLphp distribution:
`exampleauth:UserPass`
: Authenticate against a list of usernames and passwords.
`exampleauth:Static`
: Automatically log in as a user with a set of attributes.
[`ldap:LDAP`](./ldap:ldap)
: Authenticates an user to a LDAP server.
For more authentication modules, see [SimpleSAMLphp Identity Provider QuickStart](simplesamlphp-idp).
In this guide, we will use the `exampleauth:UserPass` authentication module. This module does not have any dependencies, and is therefore simple to set up.
After you have successfuly tested that everything is working with the simple `exampleauth:UserPass`, you are encouraged to setup SimpleSAMLphp IdP towards your user storage, such as an LDAP directory. (Use the links on the authentication sources above to read more about these setups. `ldap:LDAP` is the most common authentication source.)
Configuring the authentication source
-------------------------------------
The `exampleauth:UserPass` authentication source is part of the `exampleauth` module. This module isn't enabled by default, so you will have to enable it. This is done by creating a file named `enable` in `modules/exampleauth/`.
On unix, this can be done by running (from the SimpleSAMLphp installation directory):
touch modules/exampleauth/enable
The next step is to create an authentication source with this module. An authentication source is an authentication module with a specific configuration. Each authentication source has a name, which is used to refer to this specific configuration in the IdP configuration. Configuration for authentication sources can be found in `config/authsources.php`.
In this example we will use `example-userpass`, and hence that section is what matters and will be used.
array(
'exampleauth:UserPass',
'student:studentpass' => array(
'uid' => array('student'),
),
'employee:employeepass' => array(
'uid' => array('employee'),
),
),
);
?>
This configuration creates two users - `student` and `employee`, with the passwords `studentpass` and `employeepass`. The username and password are stored in the array index `student:studentpass` for the `student`-user. The attributes (only `uid` in this example) will be returned by the IdP when the user logs on.
## Configuring metadata for an SAML 2.0 IdP
If you want to setup a SAML 2.0 IdP for Google Apps, you need to configure two metadata files: `saml20-idp-hosted.php` and `saml20-sp-remote.php`.
### Configuring SAML 2.0 IdP Hosted metadata
This is the configuration of the IdP itself. Here is some example config:
// The SAML entity ID is the index of this config. Dynamic:X will automatically generate an entity ID (recommended)
$metadata['__DYNAMIC:1__'] => array(
// The hostname of the server (VHOST) that this SAML entity will use.
'host' => '__DEFAULT__',
// X.509 key and certificate. Relative to the cert directory.
'privatekey' => 'googleappsidp.pem',
'certificate' => 'googleappsidp.crt',
'auth' => 'example-userpass',
)
**Note**: You can only have one entry in the file with host equal to `__DEFAULT__`, therefore you should replace the existing entry with this one, instead of adding this entry as a new entry in the file.
### Configuring SAML 2.0 SP Remote metadata
In the `saml20-sp-remote.php` file we will configure an entry for G Suite (Google Apps) for Education. There is already an entry for G Suite in the template, but we will change the domain name:
/*
* This example shows an example config that works with G Suite (Google Apps) for education.
* What is important is that you have an attribute in your IdP that maps to the local part of the email address
* at G Suite. E.g. if your google account is foo.com, and you have a user with email john@foo.com, then you
* must set the simplesaml.nameidattribute to be the name of an attribute that for this user has the value of 'john'.
*/
$metadata['https://www.google.com/a/g.feide.no'] => array(
'AssertionConsumerService' => 'https://www.google.com/a/g.feide.no/acs',
'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
'simplesaml.nameidattribute' => 'uid',
'simplesaml.attributes' => false
);
You must also map some attributes received from the authentication module into email field sent to Google Apps. In this example, the `uid` attribute is set. When you later configure the IdP to connect to a LDAP directory or some other authentication source, make sure that the `uid` attribute is set properly, or you can configure another attribute to use here. The `uid` attribute contains the local part of the user name.
For an e-mail address `student@g.feide.no`, the `uid` should be set to `student`.
You should modify the `AssertionConsumerService` to include your G Suite domain name instead of `g.feide.no`.
For an explanation of the parameters, see the
[SimpleSAMLphp Identity Provider QuickStart](simplesamlphp-idp).
## Configure G Suite for education
Start by logging in to our G SUite for education account panel.
Then select "Advanced tools":
**Figure 1. We go to advanced tools**

Then select "Set up single sign-on (SSO)":
**Figure 2. We go to setup SSO**

Upload a certificate, such as the googleappsidp.crt created above:
**Figure 3. Uploading certificate**

Fill out the remaining fields:
The most important field is the Sign-in page URL. You can find the
correct value in your IdP metadata. Browse to your simpleSAMLphp installation,
go to the "Federation" tab, under "SAML 2.0 IdP Metadata" select "show metadata".
You will find in the metadata the XML tag ``
which contains the right URL to input in the field, it will look something
like this:
https://dev2.andreas.feide.no/simplesaml/saml2/idp/SSOService.php
You must also configure the IdP initiated Single LogOut endpoint of your server.
You will find this in your metadata XML in the tag
``. It will look something like:
http://dev2.andreas.feide.no/simplesaml/saml2/idp/SingleLogoutService.php
again, using the host name of your IdP server.
The Sign-out page or change password URL can be static pages on your server.
The network mask determines which IP addresses will be asked for SSO login.
IP addresses not matching this mask will be presented with the normal G Suite login page.
It is normally best to leave this field empty to enable authentication for all URLs.
**Figure 4. Fill out the remaining fields**

### Add a user in G Suite that is known to the IdP
Before we can test login, a new user must be defined in G Suite. This user must have a mail field matching the email prefix mapped from the attribute as described above in the metadata section.
## Test to login to G Suite for education
Go to the URL of your mail account for this domain, the URL is similar to the following:
http://mail.google.com/a/yourgoogleappsdomain.com
replacing the last part with your own G Suite domain name.
## Security Considerations
Make sure that your IdP server runs HTTPS (TLS). The Apache documentation contains information for how to configure HTTPS.
Support
-------
If you need help to make this work, or want to discuss SimpleSAMLphp with other users of the software, you are fortunate: Around SimpleSAMLphp there is a great Open source community, and you are welcome to join! The forums are open for you to ask questions, contribute answers other further questions, request improvements or contribute with code or plugins of your own.
- [SimpleSAMLphp homepage](https://simplesamlphp.org)
- [List of all available SimpleSAMLphp documentation](https://simplesamlphp.org/docs/)
- [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
simplesamlphp-1.15.3/docs/simplesamlphp-upgrade-notes-1.9.md 0000644 0000000 0000000 00000002277 13245225037 022400 0 ustar root root Upgrade notes for SimpleSAMLphp 1.9
===================================
* The OpenID client "linkback" URL has changed from `.../module.php/openid/consumer.php` to `.../module.php/openid/linkback.php`.
* Support for CA path validation has been removed from SAML 2.0.
* The X-Frame-Options has been added to the default templates, to prevent the pages from being loaded in iframes.
* Access permissions of generated files are now restricted to the current user.
* The code to set cookies now requires PHP version >= 5.2. (PHP version 5.2.0 or newer has been the only supported version for a while, but it has in some cases been possible to run SimpleSAMLphp with older versions.)
* It used to be possible to set an array of endpoints for the SingleSignOnService in `saml20-idp-hosted.php`. That is no longer supported.
* The `aselect` module has been replaced with a new module. The new module gives us better error handling and support for request signing, but we lose support for A-Select Cross.
* There has been various fixes in the session exipration handling. As a result of this, sessions may get a shorter lifetime (if the IdP places a limit on the lifetime, this limit will now be honored).
simplesamlphp-1.15.3/docs/simplesamlphp-upgrade-notes-1.6.md 0000644 0000000 0000000 00000002737 13245225037 022376 0 ustar root root Upgrade notes for SimpleSAMLphp 1.6
===================================
* This release requires PHP version >= 5.2.0, as that was the first version to include `json_decode()`.
It is possible that it may work with version of PHP >= 5.1.2 if the [JSON PECL extesion](http://pecl.php.net/package/json) is enabled, but this is untested.
* The secure-flag is no longer automatically set on the session cookie.
This was changed to avoid hard to diagnose session problems.
There is a new option `session.cookie.secure` in `config.php`, which can be used to enable secure cookies.
* Dictionaries have moved to JSON format.
The PHP format is still supported, but all dictionaries included with SimpleSAMLphp are in JSON format.
* The iframe-specific logout endpoints on the IdP have been merged into the normal logout endpoints.
This means that the metadata no longer needs to be changed when switching between logout handlers.
The old iframe logout endpoints are now deprecated, and the generated metadata will only include the normal logout endpoint.
* As a result of the changed metadata classes, all metadata elements now have a `md:`-prefix.
This does not change the content of the metadata, just its expression.
* The deprecated functions `init(...)` and `setAuthenticated(...)` in the `SimpleSAML_Session` class have been removed.
Code which relies on those functions should move to using `SimpleSAML_Session::getInstance()` and `$session->doLogin(...)`.
simplesamlphp-1.15.3/docs/simplesamlphp-idp.md 0000644 0000000 0000000 00000025177 13245225037 020076 0 ustar root root SimpleSAMLphp Identity Provider QuickStart
===========================================
This guide will describe how to configure SimpleSAMLphp as an identity provider (IdP). You should previously have installed SimpleSAMLphp as described in [the SimpleSAMLphp installation instructions](simplesamlphp-install)
Enabling the Identity Provider functionality
--------------------------------------------
The first that must be done is to enable the identity provider functionality. This is done by editing `config/config.php`. The options `enable.saml20-idp` and `enable.shib13-idp` controls whether SAML 2.0 and Shibboleth 1.3 support is enabled. Enable one or both of those by assigning `true` to them:
'enable.saml20-idp' => true,
'enable.shib13-idp' => true,
Authentication module
---------------------
The next step is to configure the way users authenticate on your IdP. Various modules in the `modules/` directory provides methods for authenticating your users. This is an overview of those that are included in the SimpleSAMLphp distribution:
[`authcrypt:Hash`](./authcrypt:authcrypt)
: Username & password authentication with hashed passwords.
[`authcrypt:Htpasswd`](./authcrypt:authcrypt)
: Username & password authentication against .htpasswd file.
[`authX509:authX509userCert`](./authX509:authX509)
: Authenticate against a LDAP database with a SSL client certificate.
`exampleauth:UserPass`
: Authenticate against a list of usernames and passwords.
`exampleauth:Static`
: Automatically log in as a user with a set of attributes.
[`ldap:LDAP`](./ldap:ldap)
: Authenticates an user to a LDAP server.
[`ldap:LDAPMulti`](./ldap:ldap)
: Authenticates an user to one of several LDAP server.
The user can choose the LDAP server from a dropdown list.
[`sqlauth:SQL`](./sqlauth:sql)
: Authenticate an user against a database.
[`radius:Radius`](./radius:radius)
: Authenticates an user to a Radius server.
[`InfoCard:ICAuth`](https://github.com/simplesamlphp/simplesamlphp-module-infocard/blob/master/README.md)
: Authenticate with an InfoCard.
[`multiauth:MultiAuth`](./multiauth:multiauth)
: Allow the user to select from a list of authentication sources.
`openid:OpenIDConsumer`
: Authenticate against an OpenID provider.
[`saml:SP`](./saml:sp)
: Authenticate against a SAML IdP. Can be used for bridging.
`authYubiKey:YubiKey`
: Authenticate with [an YubiKey](http://www.yubico.com/products/yubikey/).
[`authfacebook:Facebook`](./authfacebook:authfacebook)
: Authenticate with a Facebook ID.
[`authtwitter:Twitter`](./authtwitter:oauthtwitter)
: Authenticate with your Twitter account using the Twitter OAuth API.
[`papi:PAPI`](https://github.com/rediris-es/simplesamlphp-module-papi/blog/master/README.md)
: Authenticate by means of the PAPI protocol.
In this guide, we will use the `exampleauth:UserPass` authentication module. This module does not have any dependencies, and is therefore simple to set up.
Configuring the authentication module
-------------------------------------
The `exampleauth:UserPass` authentication module is part of the `exampleauth` module. This module isn't enabled by default, so you will have to enable it. This is done by creating a file named `enable` in `modules/exampleauth/`.
On unix, this can be done by running (from the SimpleSAMLphp
installation directory):
touch modules/exampleauth/enable
The next step is to create an authentication source with this module. An authentication source is an authentication module with a specific configuration. Each authentication source has a name, which is used to refer to this specific configuration in the IdP configuration. Configuration for authentication sources can be found in `config/authsources.php`.
In this setup, this file should contain a single entry:
array(
'exampleauth:UserPass',
'student:studentpass' => array(
'uid' => array('student'),
'eduPersonAffiliation' => array('member', 'student'),
),
'employee:employeepass' => array(
'uid' => array('employee'),
'eduPersonAffiliation' => array('member', 'employee'),
),
),
);
This configuration creates two users - `student` and `employee`, with the passwords `studentpass` and `employeepass`. The username and password is stored in the array index (`student:studentpass` for the `student`-user. The attributes for each user is configured in the array referenced by the index. For the student user, these are:
array(
'uid' => array('student'),
'eduPersonAffiliation' => array('member', 'student'),
),
The attributes will be returned by the IdP when the user logs on.
Creating a SSL self signed certificate
--------------------------------------
Here is an example of an `openssl`-command which can be used to generate a new private key key and the corresponding self-signed certificate.
This key and certificate can be used to sign SAML messages:
openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes -out example.org.crt -keyout example.org.pem
The certificate above will be valid for 10 years.
### Note ###
SimpleSAMLphp will only work with RSA certificates. DSA certificates are not supported.
Configuring the IdP
-------------------
The IdP is configured by the metadata stored in
`metadata/saml20-idp-hosted.php` and `metadata/shib13-idp-hosted.php`.
This is a minimal configuration of a SAML 2.0 IdP:
'__DEFAULT__',
/*
* The private key and certificate to use when signing responses.
* These are stored in the cert-directory.
*/
'privatekey' => 'example.org.pem',
'certificate' => 'example.org.crt',
/*
* The authentication source which should be used to authenticate the
* user. This must match one of the entries in config/authsources.php.
*/
'auth' => 'example-userpass',
);
For more information about available options in the idp-hosted metadata
files, see the [IdP hosted reference](simplesamlphp-reference-idp-hosted).
Using the `uri` NameFormat on attributes
----------------------------------------
The [interoperable SAML 2 profile](http://saml2int.org/profile/current) specifies that attributes should be delivered using the `urn:oasis:names:tc:SAML:2.0:attrname-format:uri` NameFormat.
We therefore recommended enabling this in new installations.
This can be done by adding the following to the saml20-idp-hosted configuration:
'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
'authproc' => array(
// Convert LDAP names to oids.
100 => array('class' => 'core:AttributeMap', 'name2oid'),
),
Adding SPs to the IdP
---------------------
The identity provider you are configuring needs to know about the service providers you are going to connect to it.
This is configured by metadata stored in `metadata/saml20-sp-remote.php` and `metadata/shib13-sp-remote.php`.
This is a minimal example of a `metadata/saml20-sp-remote.php` metadata file for a SimpleSAMLphp SP:
'https://sp.example.org/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp',
'SingleLogoutService' => 'https://sp.example.org/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp',
);
Note that the URI in the entityID and the URLs to the AssertionConsumerService and SingleLogoutService endpoints change between different service providers.
If you have the metadata of the remote SP as an XML file, you can use the built-in XML to SimpleSAMLphp metadata converter, which by default is available as `/admin/metadata-converter.php` in your SimpleSAMLphp installation.
For more information about available options in the sp-remote metadata files, see the [SP remote reference](simplesamlphp-reference-sp-remote).
Adding this IdP to other SPs
----------------------------
The method for adding this IdP to a SP varies between different types of SPs. In general, most SPs need some metadata from the IdP. This should be available from `/saml2/idp/metadata.php` and `/shib13/idp/metadata.php`.
Testing the IdP
---------------
The simplest way to test the IdP is to configure a SimpleSAMLphp SP
on the same machine. See the instructions for
[configuring SimpleSAMLphp as an SP](simplesamlphp-sp).
### Note ###
When running a SimpleSAMLphp IdP and a SimpleSAMLphp SP on the same computer, the SP and IdP **MUST** be configured with different hostnames. This prevents cookies from the SP to interfere with cookies from the IdP.
Support
-------
If you need help to make this work, or want to discuss SimpleSAMLphp with other users of the software, you are fortunate: Around SimpleSAMLphp there is a great Open source community, and you are welcome to join! The forums are open for you to ask questions, contribute answers other further questions, request improvements or contribute with code or plugins of your own.
- [SimpleSAMLphp homepage](https://simplesamlphp.org)
- [List of all available SimpleSAMLphp documentation](https://simplesamlphp.org/docs/)
- [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
A. IdP-first setup
------------------
If you do not want to start the SSO flow at the SP, you may use the IdP-first setup. To do this, redirect the user to the SSOService endpoint on the IdP with one parameter `spentityid` that match the SP EntityId that the user should be logged into.
Here is an example of such a URL:
https://idp.example.org/simplesaml/saml2/idp/SSOService.php?spentityid=sp.example.org
If the SP is a SimpleSAMLphp SP, you must also specify a `RelayState` parameter for the SP.
This must be set to a URL the user should be redirected to after authentication.
The `RelayState` parameter can be specified in the [SP configuration](./saml:sp), or it can be sent from the IdP.
To send the RelayState parameter from a SimpleSAMLphp IdP, specify it in the query string to SSOService.php:
https://idp.example.org/simplesaml/saml2/idp/SSOService.php?spentityid=sp.example.org&RelayState=https://sp.example.org/welcome.php
To set it in the SP configuration, add it to `authsources.php`:
'default-sp' => array(
'saml:SP',
'RelayState' => 'https://sp.example.org/welcome.php',
),
simplesamlphp-1.15.3/docs/README 0000644 0000000 0000000 00000000412 13245225037 014765 0 ustar root root Updated: January 15th, 2015
All you need to know to install and configure simpleSAMLphp is available at:
https://simplesamlphp.org/docs/
simpleSAMLphp homepage:
https://simplesamlphp.org/
simpleSAMLphp mailinglist (for support):
https://simplesamlphp.org/lists
simplesamlphp-1.15.3/docs/simplesamlphp-authproc.md 0000644 0000000 0000000 00000025412 13245225037 021137 0 ustar root root Authentication Processing Filters in SimpleSAMLphp
==================================================
In SimpleSAMLphp, there is an API where you can *do stuff* at the IdP after authentication is complete, and just before you are sent back to the SP. The same API is available on the SP, after you have received a successful Authentication Response from the IdP and before you are sent back to the SP application.
Authentication processing filters postprocess authentication information received from authentication sources. It is possible to use this for additional authentication checks, requesting the user's consent before delivering attributes about the user, modifying the user's attributes, and other things which should be performed before returning the user to the service provider he came from.
Examples of neat things to do using Authentication Processing Filters:
* Filter out a subset of available attributes that are sent to a SP.
* Modify the name of attributes.
* Generate new attributes that are composed of others, for example eduPersonTargetedID.
* Ask the user for consent, before the user is sent back to a service.
* Implement basic Access Control on the IdP (not neccessarily a good idea), limiting access for some users to some SPs.
Be aware that Authentication Proccessing Filters do replace some of the preivous features in SimpleSAMLphp, named:
* `attributemap`
* `attributealter`
* attribute filter
Later in this document, we will desribe in detail the alternative Authentication Proccessing Filters that will replicate these functionalities.
How to configure Auth Proc Filters
----------------------------------
*Auth Proc Filters* can be set globally, or to be specific for only one SP or one IdP. That means there are five locations where you can configure *Auth Proc Filters*:
* Globally in `config.php`
* On the SP: Specific for only the SP in `authsources.php`
* On the SP: Specific for only one remote IdP in `saml20-idp-remote` or `shib13-idp-remote`
* On the IdP: Specific for only one hosted IdP in `saml20-idp-hosted` or `shib13-idp-hosted`
* On the IdP: Specific for only one remote SP in `saml20-sp-remote` or `shib13-sp-remote`
The configuration of *Auth Proc Filters* is a list of filters with priority as *index*. Here is an example of *Auth Proc Filters* configured in `config.php`:
'authproc.idp' => array(
10 => array(
'class' => 'core:AttributeMap',
'addurnprefix'
),
20 => 'core:TargetedID',
50 => 'core:AttributeLimit',
90 => array(
'class' => 'consent:Consent',
'store' => 'consent:Cookie',
'focus' => 'yes',
'checked' => TRUE
),
),
This configuration will execute *Auth Proc Filters* one by one, with the priority value in increasing order. When *Auth Proc Filters* is configured in multiple places, in example both globally, in the hosted IdP and remote SP metadata, then the list is interleaved sorted by priority.
The most important parameter of each item on the list is the *class* of the *Auth Proc Filter*. The syntax of the class is `modulename:classname`. As an example the class definition `core:AttributeLimit` will be expanded to look for the class `sspmod_core_Auth_Process_AttributeLimit`. The location of this class file *must* then be: `modules/core/lib/Auth/Process/AttributeLimit.php`.
You will see that a bunch of useful filters is included in the `core` module. In addition the `consent` module that is included in the SimpleSAMLphp distribution implements a filter. Beyond that, you are encouraged to create your own filters and share with the community. If you have created a cool *Auth Proc Filter* that does something useful, let us know, and we may share it on the [SimpleSAMLphp web site][].
[SimpleSAMLphp web site]: http://simplesamlphp.org
When you know the class definition of a filter, and the priority, the simple way to configure the filter is:
20 => 'core:TargetedID',
This is analogous to:
20 => array(
'class' => 'core:TargetedID'
),
Some *Auth Proc Filters* have optional or required *parameters*. To send parameters to *Auth Proc Filters*, you need to choose the second of the two alernatives above. Here is an example of provided parameters to the consent module:
90 => array(
'class' => 'consent:Consent',
'store' => 'consent:Cookie',
'focus' => 'yes',
'checked' => TRUE
),
### Filters in `config.php`
Global *Auth Proc Filters* are configured in the `config.php` file. You will see that the config template already includes an example configuration.
There are two config parameters:
* `authproc.idp` and
* `authproc.sp`
The filters in `authproc.idp` will be executed at the IdP side regardless of which IdP and SP entity that is involved.
The filters in `authproc.sp` will be executed at the SP side regardless of which SP and IdP entity that is involved.
### Filters in metadata
Filters can be added both in `hosted` and `remote` metadata. Here is an example of a filter added in a metadata file:
'__DYNAMIC:1__' => array(
'host' => '__DEFAULT_',
'privatekey' => 'example.org.pem',
'certificate' => 'example.org.crt',
'auth' => 'feide',
'authproc' => array(
40 => 'preprodwarning:Warning',
),
)
The example above is in `saml20-idp-hosted`.
Auth Proc Filters included in the SimpleSAMLphp distribution
------------------------------------------------------------
The following filters are included in the SimpleSAMLphp distribution:
- [`authorize:Authorize`](./authorize:authorize): Access control based on regular expressions.
- [`consent:Consent`](./consent:consent): Ask the user for consent before transmitting attributes.
- [`core:AttributeAdd`](./core:authproc_attributeadd): Add attributes to the response.
- [`core:AttributeCopy`](./core:authproc_attributecopy): Copy existing attributes to the response.
- [`core:AttributeAlter`](./core:authproc_attributealter): Do search-and-replace on attributevalues.
- [`core:AttributeLimit`](./core:authproc_attributelimit): Limit the attributes in the response.
- [`core:AttributeMap`](./core:authproc_attributemap): Change the name of the attributes.
- [`core:AttributeRealm`](./core:authproc_attributerealm): (deprecated) Create an attribute with the realm of the user.
- [`core:GenerateGroups`](./core:authproc_generategroups): Generate a `group` attribute for the user.
- [`core:LanguageAdaptor`](./core:authproc_languageadaptor): Transfering language setting from IdP to SP.
- [`core:PHP`](./core:authproc_php): Modify attributes with custom PHP code.
- [`core:ScopeAttribute`](./core:authproc_scopeattribute): Add scope to attribute.
- [`core:ScopeFromAttribute`](./core:authproc_scopefromattribute): Create a new attribute based on the scope on a different attribute.
- [`core:StatisticsWithAttribute`](./core:authproc_statisticswithattribute): Create a statistics logentry.
- [`core:TargetedID`](./core:authproc_targetedid): Generate the `eduPersonTargetedID` attribute.
- [`core:WarnShortSSOInterval`](./core:authproc_warnshortssointerval): Give a warning if the user logs into the same SP twice within a few seconds.
- [`expirycheck:ExpiryDate`](./expirycheck:expirycheck): Block access to accounts that have expired.
- [`preprodwarning:Warning`](./preprodwarning:warning): Warn the user about accessing a test IdP.
- [`saml:AttributeNameID`](./saml:nameid): Generate custom NameID with the value of an attribute.
- [`saml:ExpectedAuthnContextClassRef`](./saml:authproc_expectedauthncontextclassref): Verify the user's authentication context.
- [`saml:FilterScopes`](./saml:filterscopes): Filter attribute values with scopes forbidden for an IdP.
- [`saml:NameIDAttribute`](./saml:nameidattribute): Create an attribute based on the NameID we receive from the IdP.
- [`saml:PersistentNameID`](./saml:nameid): Generate persistent NameID from an attribute.
- [`saml:PersistentNameID2TargetedID`](./saml:nameid): Store persistent NameID as eduPersonTargetedID.
- [`saml:TransientNameID`](./saml:nameid): Generate transient NameID.
- [`smartattributes:SmartID`](./smartattributes:smartattributes): Generate user ID attribute based on several attributes.
Writing your own Auth Proc Filter
---------------------------------
Look at the included *Auth Proc Filters* as examples. Copy the classes into your own module and start playing around.
Authentication processing filters are created by creating a class under `Auth/Process/` in a module. This class is expected to subclass `SimpleSAML_Auth_ProcessingFilter`. A filter must implement at least one function - the `process(&$request)`-function. This function can access the `$request`-array to add, delete and modify attributes, and can also do more advanced processing based on the SP/IdP metadata (which is also included in the `$request`-array). When this function returns, it is assumed that the filter has finished processing.
If a filter for some reason needs to redirect the user, for example to show a web page, it should save the current request. Upon completion it should retrieve the request, update it with the changes it is going to make, and call `SimpleSAML_Auth_ProcessingChain::resumeProcessing`. This function will continue processing the next configured filter.
Requirements for authentication processing filters:
- Must be derived from the `SimpleSAML_Auth_ProcessingFilter`-class.
- If a constructor is implemented, it must first call the parent constructor, passing along all parameters, before accessing any of the parameters. In general, only the $config parameter should be accessed.
- The `process(&$request)`-function must be implemented. If this function completes, it is assumed that processing is completed, and that the $request array has been updated.
- If the `process`-function does not return, it must at a later time call `SimpleSAML_Auth_ProcessingChain::resumeProcessing` with the new request state. The request state must be an update of the array passed to the `process`-function.
- No pages may be shown to the user from the `process`-function. Instead, the request state should be saved, and the user should be redirected to a new page. This must be done to prevent unpredictable events if the user for example reloads the page.
- No state information should be stored in the filter object. It must instead be stored in the request state array. Any changes to variables in the filter object may be lost.
- The filter object must be serializable. It may be serialized between being constructed and the call to the `process`-function. This means that, for example, no database connections should be created in the constructor and later used in the `process`-function.
Don't hestitate to ask on the SimpleSAMLphp mailinglist if you have problems or questions, or want to share your *Auth Proc Filter* with others.
simplesamlphp-1.15.3/docs/simplesamlphp-theming.md 0000644 0000000 0000000 00000011602 13245225037 020741 0 ustar root root Theming the user interface in SimpleSAMLphp
===========================================
In SimpleSAMLphp every part that needs to interact with the user by using a web page, uses templates to present the XHTML. SimpleSAMLphp comes with a default set of templates that presents a anonymous look.
You may create your own theme, where you add one or more template files that will override the default ones. This document explains how to achieve that.
How themes work
--------------------
If you want to customize the UI, the right way to do that is to create a new **theme**. A theme is a set of templates that can be configured to override the default templates.
### Configuring which theme to use
In `config.php` there is a configuration option that controls theming. Here is an example:
'theme.use' => 'fancymodule:fancytheme',
The `theme.use` parameter points to which theme that will be used. If some functionality in SimpleSAMLphp needs to present UI in example with the `logout.php` template, it will first look for `logout.php` in the `theme.use` theme, and if not found it will all fallback to look for the base templates.
All required templates SHOULD be available as a base in the `templates` folder, and you SHOULD never change the base templates. To customize UI, add a new theme within a module that overrides the base templates, instead of modifying it.
### Templates that include other files
A template file may *include* other files. For example all the default templates will include a header and footer: the `login.php` template will first include `includes/header.php` then present the login page, and then include `includes/footer.php`.
SimpleSAMLphp allows themes to override the included templates files only, if needed. That means you can create a new theme `fancytheme` that includes only a header and footer. The header file refers to the CSS files, which means that a simple way of making a new look on SimpleSAMLphp is to create a new theme, and copy the existing header, but point to your own CSS instead of the default CSS.
Creating your first theme
-------------------------
The first thing you need to do is having a SimpleSAMLphp module to place your theme in. If you do not have a module already, create a new one:
cd modules
mkdir mymodule
cd mymodule
touch default-enable
Then within this module, you can create a new theme named `fancytheme`.
cd modules/mymodule
mkdir -p themes/fancytheme
Now, configure SimpleSAMLphp to use your new theme in `config.php`:
'theme.use' => 'mymodule:fancytheme',
Next, we create `themes/fancytheme/default/includes`, and copy the header file from the base theme:
cp templates/includes/header.php modules/mymodule/themes/fancytheme/default/includes/
In the `modules/mymodule/themes/fancytheme/default/includes/header.php` type in something and go to the SimpleSAMLphp front page to see that your new theme is in use.
A good start is to modify the reference to the default CSS:
to in example:
Examples
---------------------
To override the frontpage body, add the file:
modules/mymodule/themes/fancytheme/default/frontpage.php
In the path above `default` means that the frontpage template is not part of any modules. If you are replacing a template that is part of a module, then use the module name instead of `default`.
For example, to override the `preprodwarning` template, (the file is located in `modules/preprodwarning/templates/warning.php`), you need to add a new file:
modules/mymodule/themes/fancytheme/preprodwarning/warning.php
Say in a module `foomodule`, some code requests to present the `bar.php` template, SimpleSAMLphp will:
1. first look in your theme for a replacement: `modules/mymodule/themes/fancytheme/foomodule/bar.php`.
2. If not found, it will use the base template of that module: `modules/foomodule/templates/bar.php`
Adding resource files
---------------------
You can put resource files within the www folder of your module, to make your module completely independent with included css, icons etc.
```
modules
└───mymodule
└───themes
└───www
└───logo.png
└───style.css
```
Reference these resources in your custom PHP templates under `themes/fancytheme` by using a generator for the URL:
```php
```
Example for a custom CSS stylesheet file:
```html
```
simplesamlphp-1.15.3/docs/simplesamlphp-install.md 0000644 0000000 0000000 00000036747 13245225037 020775 0 ustar root root SimpleSAMLphp Installation and Configuration
============================================
SimpleSAMLphp news and documentation
------------------------------------
This document is part of the SimpleSAMLphp documentation suite.
* [List of all SimpleSAMLphp documentation](https://simplesamlphp.org/docs)
* [SimpleSAMLphp homepage](https://simplesamlphp.org)
Development version
--------------------
This document is about the latest stable version of SimpleSAMLphp.
If you want to install the development version, look at the instructions for [installing SimpleSAMLphp from the repository](simplesamlphp-install-repo).
Prerequisites
-------------
* Some webserver capable of executing PHP scripts.
* PHP version >= 5.4.0.
* Support for the following PHP extensions:
* Always required: `date`, `dom`, `hash`, `libxml`, `openssl`, `pcre`, `SPL`, `zlib`, `json`, `mbstring`
* When automatically checking for latest versions, and used by some modules: `cURL`
* When authenticating against LDAP server: `ldap`
* When authenticating against RADIUS server: `radius`
* When using native PHP session handler: `session`
* When saving session information to a memcache server: `memcache`
* When using databases:
* Always: `PDO`
* Database driver: (`mysql`, `pgsql`, ...)
* Support for the following PHP packages:
* When saving session information to a Redis server: `predis`
What actual packages are required for the various extensions varies between different platforms and distributions.
Download and install SimpleSAMLphp
----------------------------------
The most recent release of SimpleSAMLphp is found at [https://simplesamlphp.org/download](https://simplesamlphp.org/download).
Go to the directory where you want to install SimpleSAMLphp, and extract the archive file you just downloaded:
cd /var
tar xzf simplesamlphp-1.x.y.tar.gz
mv simplesamlphp-1.x.y simplesamlphp
## Upgrading from a previous version of SimpleSAMLphp
Extract the new version:
cd /var
tar xzf simplesamlphp-1.x.y.tar.gz
Copy the configuration files from the previous version (in case the configuration directory is inside SimpleSAMLphp,
keep reading for other alternatives):
cd /var/simplesamlphp-1.x.y
rm -rf config metadata
cp -rv ../simplesamlphp/config config
cp -rv ../simplesamlphp/metadata metadata
Replace the old version with the new version:
cd /var
mv simplesamlphp simplesamlphp.old
mv simplesamlphp-1.x.y simplesamlphp
If the format of the config files or metadata has changed from your previous version of SimpleSAMLphp (check the revision log), you may have to update your configuration and metadata after updating the SimpleSAMLphp code:
### Upgrading configuration files
A good approach is to run a `diff` between your previous `config.php` file and the new `config.php` file located in `config-templates/config.php`, and apply relevant modifications to the new template.
This will ensure that all new entries in the latest version of config.php are included, as well as preserve your local modifications.
### Upgrading metadata files
Most likely the metadata format is backwards compatible. If not, you should receive a very clear error message at startup indicating how and what you need to update. You should look through the metadata in the metadata-templates directory after the upgrade to see whether recommended defaults have been changed.
### Alternative location for configuration files
By default, SimpleSAMLphp looks for its configuration in the `config` directory in the root of its own directory. This
has some drawbacks, like making it harder to use SimpleSAMLphp as a composer dependency, or to package it for different
operating systems.
However, it is now possible to specify an alternate location for the configuration directory by setting an environment
variable with this location. This way, the configuration directory doesn't need to be inside the library's directory,
making it easier to manage and to update. The simplest way to set this environment variable is to set it in your web
server's configuration. See the next section for more information.
Configuring Apache
------------------
Examples below assume that SimpleSAMLphp is installed in the default location, `/var/simplesamlphp`. You may choose another location, but this requires a path update in a few files. See Appendix for details ‹Installing SimpleSAMLphp in alternative locations›.
The only subdirectory of `SimpleSAMLphp` that needs to be accessible from the web is `www`. There are several ways of exposing SimpleSAMLphp depending on the way web sites are structured on your Apache web server. The following is just one possible configuration.
Find the Apache configuration file for the virtual hosts where you want to run SimpleSAMLphp. The configuration may look like this:
ServerName service.example.com
DocumentRoot /var/www/service.example.com
SetEnv SIMPLESAMLPHP_CONFIG_DIR /var/simplesamlphp/config
Alias /simplesaml /var/simplesamlphp/www
# For Apache 2.2:
Order allow,deny
Allow from all
# For Apache 2.4:
Require all granted
Note the `Alias` directive, which gives control to SimpleSAMLphp for all urls matching `http(s)://service.example.com/simplesaml/*`. SimpleSAMLphp makes several SAML interfaces available on the web; all of them are included in the `www` subdirectory of your SimpleSAMLphp installation. You can name the alias whatever you want, but the name must be specified in the `config.php` file of SimpleSAMLphp as described in [the section called “SimpleSAMLphp configuration: config.php”](#sect.config "SimpleSAMLphp configuration: config.php"). Here is an example of how this configuration may look like in `config.php`:
$config = array (
[...]
'baseurlpath' => 'simplesaml/',
Note also the `SetEnv` directive. It sets the `SIMPLESAMLPHP_CONFIG_DIR` environment variable, in this case, to the
default location for the configuration directory. You can omit this environment variable, and SimpleSAMLphp will
then look for the `config` directory inside its own directory. If you need to move your configuration to a different
location, you can use this environment variable to tell SimpleSAMLphp where to look for configuration files.
This works only for the `config` directory. If you need your metadata to be in a different directory too, use the
`metadatadir` configuration option to specify the location.
This is just the basic configuration to get things working. For a checklist
further completing your documentation, please see
[Maintenance and configuration: Apache](simplesamlphp-maintenance#section_4).
SimpleSAMLphp configuration: config.php
---------------------------------------
There is a few steps that you should edit in the main configuration
file, `config.php`, right away:
- Set a administrator password. This is needed to access some of the pages in your SimpleSAMLphp installation web interface.
'auth.adminpassword' => 'setnewpasswordhere',
Hashed passwords can also be used here. See the [`authcrypt`](./authcrypt:authcrypt) documentation for more information.
- Set a secret salt. This should be a random string. Some parts of the SimpleSAMLphp needs this salt to generate cryptographically secure hashes. SimpleSAMLphp will give an error if the salt is not changed from the default value. The command below can help you to generated a random string on (some) unix systems:
tr -c -d '0123456789abcdefghijklmnopqrstuvwxyz' /dev/null;echo
Here is an example of the config option:
'secretsalt' => 'randombytesinsertedhere',
-
Set technical contact information. This information will be
available in the generated metadata. The e-mail address will also
be used for receiving error reports sent automatically by
SimpleSAMLphp. Here is an example:
'technicalcontact_name' => 'John Smith',
'technicalcontact_email' => 'john.smith@example.com',
-
If you use SimpleSAMLphp in a country where English is not
widespread, you may want to change the default language from
English to something else:
'language.default' => 'no',
-
Set the timezone which you use:
'timezone' => 'Europe/Oslo',
* [List of Supported Timezones at php.net](http://php.net/manual/en/timezones.php)
Configuring PHP
---------------
### Sending e-mails from PHP
Some parts of SimpleSAMLphp will allow you to send e-mails. In example sending error reports to technical admin, as well as sending in metadata to the federation administrators. If you want to make use of this functionality, you should make sure your PHP installation is configured to be able to send e-mails. It's a common problem that PHP is not configured to send e-mails properly. The configuration differs from system to system. On UNIX, PHP is using sendmail, on Windows SMTP.
Enable modules
--------------
If you want to enable some of the modules that are installed with SimpleSAMLphp, but are disabled by default, you should create an empty file in the module directory named `enable`.
# Enabling the consent module
cd modules
ls -l
cd consent
touch enable
If you later want to disable the module, rename the `enable` file
to `disable`.
cd modules/consent
mv enable disable
The SimpleSAMLphp installation webpage
--------------------------------------
After installing SimpleSAMLphp, you can access the homepage of your installation, which contains some information and a few links to the test services. The URL of an installation can be e.g.:
https://service.example.org/simplesaml/
The exact link depends on how you set it up with Apache, and of course on your hostname.
### Warning
Don't click on any of the links yet, because they require you to
either have setup SimpleSAMLphp as an Service Provider or as an
Identity Provider.
Here is an example screenshot of what the SimpleSAMLphp page looks
like:

### Check your PHP environment
At the bottom of the installation page are some green lights. simpleSAML runs some tests to see whether required and recommended prerequisites are met. If any of the lights are red, you may have to add some extensions or modules to PHP, e.g. you need the PHP LDAP extension to use the LDAP authentication module.
## Next steps
You have now successfully installed SimpleSAMLphp, and the next steps depends on whether you want to setup a service provider, to protect a website by authentication or if you want to setup an identity provider and connect it to a user catalog. Documentation on bridging between federation protocols is found in a separate document.
* [Using SimpleSAMLphp as a SAML Service Provider](simplesamlphp-sp)
* [Hosted SP Configuration Reference](./saml:sp)
* [IdP remote reference](simplesamlphp-reference-idp-remote)
* [Connecting SimpleSAMLphp as a SP to UK Access Federation or InCommon](simplesamlphp-ukaccess)
* [Upgrading - migration to use the SAML authentication source](simplesamlphp-sp-migration)
* [Identity Provider QuickStart](simplesamlphp-idp)
* [IdP hosted reference](simplesamlphp-reference-idp-hosted)
* [SP remote reference](simplesamlphp-reference-sp-remote)
* [Use case: Setting up an IdP for G Suite (Google Apps)](simplesamlphp-googleapps)
* [Identity Provider Advanced Topics](simplesamlphp-idp-more)
* [Automated Metadata Management](simplesamlphp-automated_metadata)
* [Maintenance and configuration](simplesamlphp-maintenance)
Support
-------
If you need help to make this work, or want to discuss SimpleSAMLphp with other users of the software, you are fortunate: Around SimpleSAMLphp there is a great Open source community, and you are welcome to join! The forums are open for you to ask questions, contribute answers other further questions, request improvements or contribute with code or plugins of your own.
- [SimpleSAMLphp homepage](https://simplesamlphp.org)
- [List of all available SimpleSAMLphp documentation](https://simplesamlphp.org/docs/)
- [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
Installing SimpleSAMLphp in alternative locations
-------------------------------------------------
There may be several reasons why you want to install SimpleSAMLphp
in an alternative way.
1. You are installing SimpleSAMLphp in a hosted environment where you
do not have root access, and cannot change Apache configuration.
Still you can install SimpleSAMLphp - keep on reading.
2. You have full permissions to the server, but cannot edit Apache
configuration for some reason, politics, policy or whatever.
The SimpleSAMLphp code contains one folder named `simplesamlphp`. In this folder there are a lot of subfolders for library, metadata, configuration and much more. One of these folders is named `www`. This and *only this* folder should be exposed on the web. The recommended configuration is to put the whole `simplesamlphp` folder outside the webroot, and then link in the `www` folder by using the `Alias` directive, as described in [the section called “Configuring Apache”](#sect.apacheconfig "Configuring Apache"). But this is not the only possible way.
As an example, let's see how you can install SimpleSAMLphp in your home directory on a shared hosting server.
Extract the SimpleSAMLphp archive in your home directory:
cd ~
tar xzf simplesamlphp-1.x.y.tar.gz
mv simplesamlphp-1.x.y simplesamlphp
Then you can try to make a symlink into the `public\_html` directory.
cd ~/public_html
ln -s ../simplesamlphp/www simplesaml
Next, you need to update the configuration of paths in `simplesamlphp/config/config.php`:
And, then we need to set the `baseurlpath` parameter to match the base path of the URLs to the content of your `www` folder:
'baseurlpath' => '/simplesaml/',
Now, you can go to the URL of your installation and check if things work:
http://yourcompany.com/simplesaml/
### Tip
Symlinking may fail, because some Apache configurations do not allow you to link in files from outside the public\_html folder. If so, move the folder instead of symlinking:
cd ~/public_html
mv ../simplesamlphp/www simplesaml
Now you have the following directory structure.
- `~/simplesamlphp`
-
`~/public_html/simplesaml` where `simplesaml` is the `www`
directory from the `simplesamlphp` installation directory, either
moved or a symlink.
Now, we need to make a few configuration changes. First, let's edit
`~/public_html/simplesaml/_include.php`:
Change the two lines from:
require_once(dirname(dirname(__FILE__)) . '/lib/_autoload.php');
to something like:
require_once('/var/www/simplesamlphp/lib/_autoload.php');
And then at the end of the file, you need to change another line
from:
$configdir = dirname(dirname(__FILE__)) . '/config';
to:
$configdir = '/var/www/simplesamlphp/config';
### Note
In a future version of SimpleSAMLphp we'll make this a bit easier, and let you only change the path one place, instead of three as described above.
simplesamlphp-1.15.3/docs/simplesamlphp-maintenance.md 0000644 0000000 0000000 00000031563 13245225037 021600 0 ustar root root SimpleSAMLphp Maintenance
=========================
SimpleSAMLphp news and documentation
------------------------------------
Please check the following sources of information to stay up to date with regard to SimpleSAMLphp:
* [SimpleSAMLphp documentation](http://simplesamlphp.org/docs)
* [SimpleSAMLphp homepage](https://simplesamlphp.org)
* [SimpleSAMLphp mailing lists](https://simplesamlphp.org/lists)
* [SimpleSAMLphp in twitter](https://twitter.com/simplesamlphp)
## Session management
SimpleSAMLphp has an abstraction layer for session management. That means it is possible to choose between different kind of session stores, as well as write new session store plugins.
The `store.type` configuration option in `config.php` allows you to select which method SimpleSAMLphp should use to store the session information. Currently, three session handlers are included in the distribution:
* `phpsession` uses the built in session management in PHP. This is the default, and is simplest to use. It will not work in a load-balanced environment in most configurations.
* `memcache` uses the memcache software to cache sessions in memory. Sessions can be distributed and replicated among several memcache servers, enabling both load-balancing and fail-over.
* `sql` stores the session in an SQL database.
* `redis` stores the session in Redis.
'store.type' => 'phpsession',
### Configuring PHP sessions
To use the PHP session handler, set the `store.type` configuration option in `config.php`:
'store.type' => 'phpsession',
Keep in mind that **PHP does not allow two sessions to be open at the same time**. This means if you are using PHP sessions both in your
application and in SimpleSAMLphp at the same time, **they need to have different names**. When using the PHP session handler in
SimpleSAMLphp, it is configured with different options than for other session handlers:
'session.phpsession.cookiename' => null,
'session.phpsession.savepath' => null,
'session.phpsession.httponly' => true,
Make sure to set `session.phpsession.cookiename` to a name different than the one in use by any other applications. If you are using
SimpleSAMLphp as an Identity Provider, or any other applications using it are not using the default session name, you can use the default
settings by leaving these options unset or setting them to `null`.
If you need to restore your session's application after calling SimpleSAMLphp, you can do it by calling the `cleanup()` method of the
`SimpleSAML_Session` class, like described [here](simplesamlphp-sp#section_6).
### Configuring memcache
To use the memcache session handler, set the `store.type` parameter in `config.php`:
'store.type' => 'memcache',
memcache allows you to store multiple redundant copies of sessions on different memcache servers.
The configuration parameter `memcache_store.servers` is an array of server groups. Every data item will be mirrored in every server group.
Each server group is an array of servers. The data items will be load-balanced between all servers in each server group.
Each server is an array of parameters for the server. The following options are available:
`hostname`
: Host name or ip address where the memcache server runs, or specify other transports like *unix:///path/ssp.sock* to
use UNIX domain sockets. In that case, port will be ignored and forced to *0*.
This is the only required option.
`port`
: Port number of the memcache server. If not set, the `memcache.default_port` ini setting is used. This is 11211 by
default.
The port will be forced to *0* when a UNIX domain socket is specified in *hostname*.
`weight`
: Weight of this server in this server group.
[http://php.net/manual/en/function.Memcache-addServer.php](http://php.net/manual/en/function.Memcache-addServer.php)
has more information about the weight option.
`timeout`
: Timeout for this server. By default, the timeout is 3
seconds.
Here are two examples of configuration of memcache session handling:
**Example 1. Example of redundant configuration with load balancing**
Example of redundant configuration with load balancing: This configuration makes it possible to lose both servers in the a-group or both servers in the b-group without losing any sessions. Note that sessions will be lost if one server is lost from both the a-group and the b-group.
'memcache_store.servers' => array(
array(
array('hostname' => 'mc_a1'),
array('hostname' => 'mc_a2'),
),
array(
array('hostname' => 'mc_b1'),
array('hostname' => 'mc_b2'),
),
),
**Example 2. Example of simple configuration with only one memcache server**
Example of simple configuration with only one memcache server, running on the same computer as the web server: Note that all sessions will be lost if the memcache server crashes.
'memcache_store.servers' => array(
array(
array('hostname' => 'localhost'),
),
),
The expiration value (`memcache_store.expires`) is the duration for which data should be retained in memcache. Data are dropped from the memcache servers when this time expires. The time will be reset every time the data is written to the memcache servers.
This value should always be larger than the `session.duration` option. Not doing this may result in the session being deleted from the memcache servers while it is still in use.
Set this value to 0 if you don't want data to expire.
#### Note
The oldest data will always be deleted if the memcache server runs
out of storage space.
**Example 3. Example of configuration setting for session expiration**
Here is an example of this configuration parameter:
'memcache_store.expires' => 36 * (60*60), // 36 hours.
#### Memcache PHP configuration
Configure memcache to not do internal failover. This parameter is
configured in `php.ini`.
memcache.allow_failover = Off
#### Environmental configuration
Setup a firewall restricting access to the memcache server.
Because SimpleSAMLphp uses a timestamp to check which session is most recent in a fail-over setup, it is very important to run synchronized clocks on all web servers where you run SimpleSAMLphp.
### Configuring SQL storage
To store session to a SQL database, set the `store.type` option to `sql`.
SimpleSAMLphp uses [PDO](http://www.php.net/manual/en/book.pdo.php) when accessing the database server, so the database source is configured as with a DSN.
The DSN is stored in the `store.sql.dsn` option. See the [PDO driver manual](http://www.php.net/manual/en/pdo.drivers.php) for the DSN syntax used by the different databases.
Username and password for accessing the database can be configured in the `store.sql.username` and `store.sql.password` options.
The required tables are created automatically. If you are storing data from multiple separate SimpleSAMLphp installations in the same database, you can use the `store.sql.prefix` option to prevent conflicts.
### Configuring Redis storage
To store sessions in Redis, set the `store.type` option to `redis`.
By default SimpleSAMLphp will attempt to connect to Redis on the `localhost` at port `6379`. These can be configured via the `store.redis.host` and `store.redis.port` options, respectively. You may also set a key prefix with the `store.redis.prefix` option.
## Metadata storage
Several metadata storage backends are available by default, including `flatfile`, `serialize`, `mdq` and
[`pdo`](https://simplesamlphp.org/docs/stable/simplesamlphp-metadata-pdostoragehandler). Here you have an
example configuration of different metadata sources in use at the same time:
```
'metadata.sources' => array(
array('type' => 'flatfile'),
array('type' => 'flatfile', 'directory' => 'metadata/metarefresh-kalmar'),
array('type' => 'serialize', 'directory' => 'metadata/metarefresh-ukaccess'),
),
```
You may also implement your own metadata storage handler, in a very similar way to how you would implement
your own session handler. Your class **must** extend the `SimpleSAML_Metadata_MetaDataStorageSource` class
and override the methods needed to change the backend used. This class **must** also be located in the
`lib/MetadataStore/` directory of your custom module.
Bear in mind that **your class name must follow the PSR-0 autoloading standard**. This means it needs to be
named in a particular way, with the use of namespaces being the preferred convention. For example, if your
module is named _mymodule_ and your class is named _MyMetadataHandler_, you should define it like this:
```
array('en', 'no', 'da', 'es', 'xx'),
'language.default' => 'en',
Please use the standardized two-character
[language codes as specified in ISO-639-1](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).
You also can set the default language. You should ensure that the default language is complete, as it is used as a fallback when a text is not available in the language selected by the user.
All strings that can be localized are found in the files `dictionaries/`. Add a new entry for each string, with your language code, like this:
'user_pass_header' => array(
'en' => 'Enter your username and password',
'no' => 'Skriv inn brukernavn og passord',
'xx' => 'Pooa jujjique jamba',
),
You can translate as many of the texts as you would like; a full translation is not required unless you want to make this the default language. From the end users point of view, it looks best if all text fragments used in a given screen or form is in one single language.
## Customizing the web frontend with themes
Documentation on theming is moved [to a separate document](simplesamlphp-theming).
Support
-------
If you need help to make this work, or want to discuss SimpleSAMLphp with other users of the software, you are fortunate: Around SimpleSAMLphp there is a great Open source community, and you are welcome to join! The forums are open for you to ask questions, contribute answers other further questions, request improvements or contribute with code or plugins of your own.
- [SimpleSAMLphp homepage](https://simplesamlphp.org)
- [List of all available SimpleSAMLphp documentation](http://simplesamlphp.org/docs/)
- [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
simplesamlphp-1.15.3/docs/simplesamlphp-upgrade-notes-1.5.md 0000644 0000000 0000000 00000002352 13245225037 022366 0 ustar root root Upgrade notes for SimpleSAMLphp 1.5
===================================
* `SimpleSAML_Session::isValid()`
If your code calls `$session->isValid()` without an argument, you will now have to update it to pass an argument (probably `saml2`).
The reason for this change is that calling `$session->isValid()` without an argument can easily create a security hole.
* We have introduced a new module for SAML authentication.
This authentication module supports both SAML 1.1 and SAML 2.0 IdPs.
We have also added a new authentication framework which should replace the previous redirects to the initSSO-scripts.
Relating to this change, we have also deprecated the `initSSO`-scripts for SAML 1.1 and SAML 2.0 authentication.
The old methods will still be supported for a while, but new code should probably use the new code.
See the [migration guide](simplesamlphp-sp-migration) for more information about this.
* The `request.signing` option has been removed.
That option was replaced with the `redirect.sign` and `redirect.validate` options, and has been depreceated for one year.
* The `aggregator` module's configuration file has changed name.
It was changed from `aggregator.php` to `module_aggregator.php`.
simplesamlphp-1.15.3/docs/simplesamlphp-hok-sp.md 0000644 0000000 0000000 00000004405 13245225037 020512 0 ustar root root Using Holder-of-Key Web Browser SSO Profile on a SimpleSAMLphp SP
=================================================================
This document describes how to enable the [SAML V2.0 Holder-of-Key (HoK) Web Browser SSO Profile](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-holder-of-key-browser-sso.pdf)
on a SimpleSAMLphp Service Provider (SP).
The SAML V2.0 HoK Web Browser SSO Profile is an alternate version of the standard SAML Web Browser SSO Profile. Its primary benefit is the enhanced security of the SSO process
while preserving maximum compatibility with existing deployments on client and server side.
When using this profile the communication between the user and the SP is required to be protected by the TLS protocol. Additionally, the user needs a TLS client certificate.
This certificate is usually selfsigned and stored in the certificate store of the browser or the underlying operating system.
Configuring Apache
------------------
The SP requests a client certificate from the user agent during the TLS handshake. This behaviour is enabled with the following Apache webserver configuration:
SSLEngine on
SSLCertificateFile /etc/openssl/certs/server.crt
SSLCertificateKeyFile /etc/openssl/private/server.key
SSLVerifyClient optional_no_ca
SSLOptions +ExportCertData
If the user agent can successfully prove possession of the private key associated to the public key from the certificate, the received certificate is stored in the
environment variable `SSL_CLIENT_CERT` of the webserver.
Enable HoK on SP
----------------
To enable support for the HoK SSO Profile in the SP, the `saml20.hok.assertion` option must be set to TRUE in the SP configuration.
This option can also be enabled in the `saml20-idp-remote` metadata file, but in that case the endpoint will not be added to the SP metadata.
You must also send authentication requests specifying the Holder-of-Key profile to the IdP. This is controlled by the `ProtocolBinding` option in the SP configuration.
'hok-sp' => array(
'saml:SP',
'saml20.hok.assertion' => TRUE,
'ProtocolBinding' => 'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser',
),
When this is done, you can add the metadata of your SP to the IdP and test the authentication.
simplesamlphp-1.15.3/docs/simplesamlphp-automated_metadata.md 0000644 0000000 0000000 00000020204 13245225037 023127 0 ustar root root Automated Metadata Management
=============================
Introduction
------------
If you want to connect an Identity Provider, or a Service Provider to a **federation**, you need to setup metadata for the entries that you trust. In many federations, in particular federations based upon the Shibboleth software, it is normal to setup automated distribution of metadata using the SAML 2.0 Metadata XML Format.
Some central administration or authority, provides a URL with a SAML 2.0 document including metadata for all entities in the federation.
The present document explains how to setup automated downloading and parsing of a metadata document on a specific URL.
Preparations
------------
You need to enable the following modules:
1. [cron](./cron:cron)
2. metarefresh
The cron module allows you to do tasks regularly, by setting up a cron job that calls a hook in SimpleSAMLphp.
The metarefresh module will download and parse the metadata document and store it in metadata files cached locally.
First, you will need to copy the `config-templates` files of the two modules above into the global `config/` directory.
[root@simplesamlphp] cd /var/simplesamlphp
[root@simplesamlphp simplesamlphp] touch modules/cron/enable
[root@simplesamlphp simplesamlphp] cp modules/cron/config-templates/*.php config/
[root@simplesamlphp simplesamlphp] touch modules/metarefresh/enable
[root@simplesamlphp simplesamlphp] cp modules/metarefresh/config-templates/*.php config/
Testing it manually
-------------------
It is often useful to verify that the metadata sources we want to use can be parsed and verified by metarefresh, before actually
configuring it. We can do so in the command line, by invoking metarefresh with the URL of the metadata set we want to check. For
instance, if we want to configure the metadata of the SWITCH AAI Test Federation:
cd modules/metarefresh/bin
./metarefresh.php -s http://metadata.aai.switch.ch/metadata.aaitest.xml
The `-s` option sends the output to the console (for testing purposes). If the output makes sense, continue. If you get a lot of error messages, try to read them and fix the problems that might be causing them. If you are having problems and you can't figure out the cause, you can always send an e-mail to the SimpleSAMLphp mailing list and ask for advice.
Configuring the metarefresh module
----------------------------------
Now we are going to proceed to configure the metarefresh module. First, edit the appropriate configuration file:
[root@simplesamlphp simplesamlphp]# vi config/config-metarefresh.php
Here's an example of a possible configuration for both the Kalmar Federation and UK Access Management Federation:
$config = array(
'sets' => array(
'kalmar' => array(
'cron' => array('hourly'),
'sources' => array(
array(
'src' => 'https://kalmar.feide.no/simplesaml/module.php/aggregator/?id=kalmarcentral&mimetype=text/plain&exclude=norway',
'certificates' => array(
'current.crt',
'rollover.crt',
),
'template' => array(
'tags' => array('kalmar'),
'authproc' => array(
51 => array('class' => 'core:AttributeMap', 'oid2name'),
),
),
),
),
'expireAfter' => 60*60*24*4, // Maximum 4 days cache time.
'outputDir' => 'metadata/metarefresh-kalmar/',
'outputFormat' => 'flatfile',
),
'uk' => array(
'cron' => array('hourly'),
'sources' => array(
array(
'src' => 'http://metadata.ukfederation.org.uk/ukfederation-metadata.xml',
'validateFingerprint' => 'D0:E8:40:25:F0:B1:2A:CC:74:22:ED:C3:87:04:BC:29:BB:7B:9A:40',
),
),
'expireAfter' => 60*60*24*4, // Maximum 4 days cache time.
'outputDir' => 'metadata/metarefresh-ukaccess/',
'outputFormat' => 'serialize',
),
)
);
The configuration consists of one or more metadata sets. Each metadata set has its own configuration, representing a metadata set of sources.
Some federations will provide you with detailed instructions on how to configure metarefresh to fetch their metadata automatically, like,
for instance, [the InCommon federation in the US](https://spaces.internet2.edu/x/eYHFAg). Whenever a federation provides you with specific
instructions to configure metarefresh, be sure to use them from the authoritative source.
The metarefresh module supports the following configuration options:
`cron`
: Which cron tags will refresh this metadata set.
`sources`
: An array of metadata sources that will be included in this
metadata set. The contents of this option will be described later in more detail.
`expireAfter`
: The maximum number of seconds a metadata entry will be valid.
`outputDir`
: The directory where the generated metadata will be stored. The path
is relative to the SimpleSAMLphp base directory.
`outputFormat`
: The format of the generated metadata files. This must match the
metadata source added in `config.php`.
`types`
: The sets of entities to load. An array containing strings identifying the different types of entities that will be
loaded. Valid types are:
* saml20-idp-remote
* saml20-sp-remote
* shib13-idp-remote
* shib13-sp-remote
* attributeauthority-remote
All entity types will be loaded by default.
Each metadata source has the following options:
`src`
: The source URL where the metadata will be fetched from.
`certificates`
: An array of certificate files, the filename is relative to the `cert/`-directory,
that will be used to verify the signature of the metadata. The public key will
be extracted from the certificate and everything else will be ignored. So it is
possible to use a self signed certificate that has expired. Add more than one
certificate to be able to handle key rollover. This takes precedence over
validateFingerprint.
`validateFingerprint`
: The fingerprint of the certificate used to sign the metadata. You
don't need this option if you don't want to validate the signature
on the metadata.
`template`
: This is an array which will be combined with the metadata fetched to
generate the final metadata array.
`types`
: Same as the option with the same name at the metadata set level. This option has precedence when both are specified,
allowing a more fine grained configuration for every metadata source.
After you have configured the metadata sources, you need to give the
web-server write access to the output directories. Following the previous example:
chown www-data /var/simplesamlphp/metadata/metarefresh-kalmar/
chown www-data /var/simplesamlphp/metadata/metarefresh-ukaccess/
Now you can configure SimpleSAMLphp to use the metadata fetched by metarefresh. Edit the main
config.php file, and modify the `metadata.sources` directive accordingly:
'metadata.sources' => array(
array('type' => 'flatfile'),
array('type' => 'flatfile', 'directory' => 'metadata/metarefresh-kalmar'),
array('type' => 'serialize', 'directory' => 'metadata/metarefresh-ukaccess'),
),
Remember that the `type` parameter here must match the `outputFormat` in the configuration of the module.
Configuring the cron module
---------------------------
See the [cron module documentation](./cron:cron) to configure `cron`
Once you have invoked cron, and if this operation seems to run fine, navigate to the **SimpleSAMLphp Front page** › **Federation**. Here you will see a list of all the Identity Providers trusted. They will be listed with information about the maximum duration of their cached version, such as *(expires in 96.0 hours)*.
You *may* need to adjust the below php.ini setings if the metadata files you consume are quite large.
* `memory_limit`
* `max_execution_time`
Metadata duration
-----------------
SAML metadata may supply a `cacheDuration` attribute which indicates the maximum time to keep metadata cached. Because this module is run from cron, it cannot decide how often it is run and enforce this duration on its own. Make sure to run metarefresh from cron at least as often as the shortest `cacheDuration` in your metadata sources.
simplesamlphp-1.15.3/docs/simplesamlphp-nostate.md 0000644 0000000 0000000 00000014317 13245225037 020771 0 ustar root root Debugging "State Information Lost" errors
=========================================
**"State Information Lost"** (`SimpleSAML_Error_NoState: NOSTATE`)
This is one of the most common errors that you can encounter when configuring
SimpleSAMLphp. Unfortunately, it is also a generic error that can have many
possible causes. This document will attempt to describe what this error
actually means, and some of the situations that can cause it.
What is "state information"?
----------------------------
The "state information" is data that SimpleSAMLphp stores in association with a
request. The request is typically a SAML 2.0 authentication request sent to
the IdP, but it can also be other requests.
This state information is given a random ID, e.g.
"`_2da56e07840b59191d9797442b6b665d67d855cf77`", and is saved in the session of
the user.
What does it mean that it was lost?
-----------------------------------
This means that we tried to load state information with a specified ID, but
were unable to find it in the session of the user.
What can cause it to be lost?
-----------------------------
There are several ways that this can happen, but most of them have to do
with session storage. Here we will outline some generic alternatives, and
possible solutions.
#### The domain name changed during authentication
The domain name the IdP sends the response to is configured in the metadata of
the IdP. This means that it may not match up with the domain name the user
accessed. For example we may have the following scenario:
1. The user accesses `https://www.example.org/`. A session is created for the user, and the session cookie is set for the current domain (www.example.org).
1. The user needs to be authenticated. We therefore save some information about the current status in the state array, create a SAML 2.0 authentication request, and send it to the IdP.
1. The user logs in on the IdP. The IdP then sends a response to the SP at `example.org`. However, the metadata for the SP that is registered at the IdP uses `https://example.org/` (without `www`) as the domain the response should be sent to. The authentication response is therefore sent to that domain.
1. The SP (now at `https://example.org/`) tries to load the state information associated with the authentication response it received. But, because the domain name has changed, we do not receive the session cookie of the user. We are therefore unable to find the session of the user. When we attempt to load the state information from the session we are therefore unable to find it.
There are several ways to solve this. One of the simplest is often to configure
your webserver to only use one domain, and redirect all accesses to the other
domain to the correct domain.
A different solution is to change the session cookie settings, so that they are
set for the "`example.org`" domain. If you are using PHP sessions, you should
change this in `php.ini`. If not, you should change it with the
'`session.cookie.domain`' option in `config/config.php`. In either case, it should
be set to the top-level domain with a "dot" in front of it. E.g.:
'session.cookie.domain' => '.example.org',
Or in php.ini:
session.cookie_domain = ".example.org"
Note that if you use PHP sessions, you will also have to make sure that your
application uses the same domain when it sets the cookie. How that is done
depends on your application. (See the section about mismatch between
application PHP session settings and SimpleSAMLphp session settings.)
#### Hopping between http and https
If a cookie is set during a HTTPS session, it is not available when the same
URL is later accessed over http. If your site is available over both http and
https, check that you're using https consistently throughout the configuration.
The best and most secure is to make your complete site available on https only,
and redirect any http requests to https.
#### Mismatch between PHP session settings for the application and SimpleSAMLphp
If both the application you are trying to add SAML 2.0 support to and
SimpleSAMLphp uses PHP session for session storage, and they don't agree on all
the parameters, you can end up with this error. By default, SimpleSAMLphp uses
the settings from `php.ini`, but these can be overridden in `config/config.php`.
If this is the cause of your error, you have two choices: either change
SimpleSAMLphp to use a different session storage method (e.g. memcache or sql),
or change the session settings to match between the application and
SimpleSAMLphp. In many cases it is simplest to adjust the session storage.
If you decide to make the session settings match, you should change the
settings in `php.ini`. This is to make sure that the settings apply to everything
that uses the default settings. The following options in `php.ini` must match the
settings used by the application:
* `session.save_handler`: This is the method that is used to store the session. The default is "`files`".
* `session.save_path`: This is the location the session files are saved. The default depends on your PHP installation.
* `session.name`: This is the name of the session cookie. The default is "`PHPSESSID`".
* `session.cookie_path`: The path that the session cookie is limited to. The default is "`/`", which means that it is available to all pages on your domain.
* `session.cookie_domain`: This is the domain the session cookie is limited to. The default is unset, which makes the cookie available only to the current domain.
What those settings should be set to depends on the application. The simplest
way to determine it may be to look for calls to `session_set_cookie_params` in
the application, and look at what parameters it uses.
#### A generic problem saving sessions
Sometimes the problem is caused by SimpleSAMLphp being unable to load and/or save
sessions. This can be caused by the session settings being incorrect, or by a
failure of some service required by the session storage. For example, if you
are using memcache for session storage, you need to ensure that the memcache
server is running and that the web server is able to connect to it. The same
applies if you are saving the sessions to a SQL database.
You may want to check your web server error log. If the PHP session handler
fails, it may log an error message there.
simplesamlphp-1.15.3/docs/simplesamlphp-reference-idp-hosted.md 0000644 0000000 0000000 00000037060 13245225037 023310 0 ustar root root IdP hosted metadata reference
=============================
This is a reference for the metadata files
`metadata/saml20-idp-hosted.php` and `metadata/shib13-idp-hosted.php`.
Both files have the following format:
'idp.example.org',
/* Configuration options for the first IdP. */
);
$metadata['entity-id-2'] = array(
'host' => '__DEFAULT__',
/* Configuration options for the default IdP. */
);
/* ... */
The entity ID should be an URI. It can, also be on the form
`__DYNAMIC:1__`, `__DYNAMIC:2__`, `...`. In that case, the entity ID
will be generated automatically.
The `host` option is the hostname of the IdP, and will be used to
select the correct configuration. One entry in the metadata-list can
have the host `__DEFAULT__`. This entry will be used when no other
entry matches.
Common options
--------------
`auth`
: Which authentication module should be used to authenticate users on
this IdP.
`authproc`
: Used to manipulate attributes, and limit access for each SP. See
the [authentication processing filter manual](simplesamlphp-authproc).
`certificate`
: Certificate file which should be used by this IdP, in PEM format.
The filename is relative to the `cert/`-directory.
`host`
: The hostname for this IdP. One IdP can also have the `host`-option
set to `__DEFAULT__`, and that IdP will be used when no other
entries in the metadata matches.
`logouttype`
: The logout handler to use. Either `iframe` or `traditional`. `traditional` is the default.
`OrganizationName`
: The name of the organization responsible for this IdP.
This name does not need to be suitable for display to end users.
: This option can be translated into multiple languages by specifying the value as an array of language-code to translated name:
'OrganizationName' => array(
'en' => 'Example organization',
'no' => 'Eksempel organisation',
),
: *Note*: If you specify this option, you must also specify the `OrganizationURL` option.
`OrganizationDisplayName`
: The name of the organization responsible for this IdP.
This name must be suitable for display to end users.
If this option isn't specified, `OrganizationName` will be used instead.
: This option can be translated into multiple languages by specifying the value as an array of language-code to translated name.
: *Note*: If you specify this option, you must also specify the `OrganizationName` option.
`OrganizationURL`
: A URL the end user can access for more information about the organization.
: This option can be translated into multiple languages by specifying the value as an array of language-code to translated URL.
: *Note*: If you specify this option, you must also specify the `OrganizationName` option.
`privacypolicy`
: This is an absolute URL for where an user can find a
privacypolicy. If set, this will be shown on the consent page.
`%SPENTITYID%` in the URL will be replaced with the entity id of
the service the user is accessing.
: Note that this option also exists in the SP-remote metadata, and
any value in the SP-remote metadata overrides the one configured
in the IdP metadata.
`privatekey`
: Name of private key file for this IdP, in PEM format. The filename
is relative to the `cert/`-directory.
`privatekey_pass`
: Passphrase for the private key. Leave this option out if the
private key is unencrypted.
`scope`
: An array with scopes for this IdP.
The scopes will be added to the generated XML metadata.
A scope can either be a domain name or a regular expression
matching a number of domains.
`userid.attribute`
: The attribute name of an attribute which uniquely identifies
the user. This attribute is used if SimpleSAMLphp needs to generate
a persistent unique identifier for the user. This option can be set
in both the IdP-hosted and the SP-remote metadata. The value in the
sp-remote metadata has the highest priority. The default value is
`eduPersonPrincipalName`.
: Note that this option also exists in the SP-remote metadata, and
any value in the SP-remote metadata overrides the one configured
in the IdP metadata.
`contacts`
: Specify contacts in addition to the technical contact configured through config/config.php.
For example, specifying a support contact:
'contacts' => array(
array(
'contactType' => 'support',
'emailAddress' => 'support@example.org',
'givenName' => 'John',
'surName' => 'Doe',
'telephoneNumber' => '+31(0)12345678',
'company' => 'Example Inc.',
),
),
: If you have support for a trust framework that requires extra attributes on the contact person element in your IdP metadata (for example, SIRTFI), you can specify an array of attributes on a contact.
'contacts' => array(
array(
'contactType' => 'other',
'emailAddress' => 'mailto:abuse@example.org',
'givenName' => 'John',
'surName' => 'Doe',
'telephoneNumber' => '+31(0)12345678',
'company' => 'Example Inc.',
'attributes' => array(
'xmlns:remd' => 'http://refeds.org/metadata',
'remd:contactType' => 'http://refeds.org/metadata/contactType/security',
),
),
),
SAML 2.0 options
----------------
The following SAML 2.0 options are available:
`assertion.encryption`
: Whether assertions sent from this IdP should be encrypted. The default
value is `FALSE`.
: Note that this option can be set for each SP in the SP-remote metadata.
`attributes.NameFormat`
: What value will be set in the Format field of attribute
statements. This parameter can be configured multiple places, and
the actual value used is fetched from metadata by the following
priority:
: 1. SP Remote Metadata
2. IdP Hosted Metadata
: The default value is:
`urn:oasis:names:tc:SAML:2.0:attrname-format:basic`
: Some examples of values specified in the SAML 2.0 Core
Specification:
: - `urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified`
- `urn:oasis:names:tc:SAML:2.0:attrname-format:uri` (The default
in Shibboleth 2.0)
- `urn:oasis:names:tc:SAML:2.0:attrname-format:basic` (The
default in Sun Access Manager)
: You can also define your own value.
: Note that this option also exists in the SP-remote metadata, and
any value in the SP-remote metadata overrides the one configured
in the IdP metadata.
: (This option was previously named `AttributeNameFormat`.)
`encryption.blacklisted-algorithms`
: Blacklisted encryption algorithms. This is an array containing the algorithm identifiers.
: Note that this option can be set for each SP in the [SP-remote metadata](./simplesamlphp-reference-sp-remote).
: The RSA encryption algorithm with PKCS#1 v1.5 padding is blacklisted by default for security reasons. Any assertions
encrypted with this algorithm will therefore fail to decrypt. You can override this limitation by defining an empty
array in this option (or blacklisting any other algorithms not including that one). However, it is strongly
discouraged to do so. For your own safety, please include the string 'http://www.w3.org/2001/04/xmlenc#rsa-1_5' if
you make use of this option.
`https.certificate`
: The certificate used by the webserver when handling connections.
This certificate will be added to the generated metadata of the IdP,
which is required by some SPs when using the HTTP-Artifact binding.
`nameid.encryption`
: Whether NameIDs sent from this IdP should be encrypted. The default
value is `FALSE`.
: Note that this option can be set for each SP in the [SP-remote metadata](./simplesamlphp-reference-sp-remote).
`NameIDFormat`
: The format of the NameID supported by this IdP. Defaults to the `transient` format if unspecified.
This parameter can be configured in multiple places, and the actual value used is fetched from metadata with
the following priority:
: 1. SP Remote Metadata
2. IdP Hosted Metadata
: The three most commonly used values are:
: 1. `urn:oasis:names:tc:SAML:2.0:nameid-format:transient`
2. `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent`
3. `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`
: The `transient` format will generate a new unique ID every time
the user logs in.
: To properly support the `persistent` and `emailAddress` formats,
you should configure [NameID generation filters](./saml:nameid)
on your IdP.
: Note that the value set here will be added to the metadata generated for this IdP,
in the `NameIDFormat` element.
`RegistrationInfo`
: Allows to specify information about the registrar of this SP. Please refer to the
[MDRPI extension](./simplesamlphp-metadata-extensions-rpi) document for further information.
`saml20.sendartifact`
: Set to `TRUE` to enable the IdP to send responses with the HTTP-Artifact binding.
Defaults to `FALSE`.
: Note that this requires a configured memcache server.
`saml20.hok.assertion`
: Set to `TRUE` to enable the IdP to send responses according the [Holder-of-Key Web Browser SSO Profile](./simplesamlphp-hok-idp).
Defaults to `FALSE`.
`saml20.sign.response`
: Whether `` messages should be signed.
Defaults to `TRUE`.
: Note that this option also exists in the SP-remote metadata, and
any value in the SP-remote metadata overrides the one configured
in the IdP metadata.
`saml20.sign.assertion`
: Whether `` elements should be signed.
Defaults to `TRUE`.
: Note that this option also exists in the SP-remote metadata, and
any value in the SP-remote metadata overrides the one configured
in the IdP metadata.
`sign.logout`
: Whether to sign logout messages sent from this IdP.
: Note that this option also exists in the SP-remote metadata, and
any value in the SP-remote metadata overrides the one configured
in the IdP metadata.
`SingleSignOnService`
: Override the default URL for the SingleSignOnService for this
IdP. This is an absolute URL. The default value is
`/saml2/idp/SSOService.php`
: Note that this only changes the values in the generated
metadata and in the messages sent to others. You must also
configure your webserver to deliver this URL to the correct PHP
page.
`SingleSignOnServiceBinding`
: List of SingleSignOnService bindings that the IdP will claim support for.
: Possible values:
* `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect`
* `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST`
: Defaults to HTTP-Redirect binding. Please note that the order
specified will be kept in the metadata, making the first binding
the default one.
`SingleLogoutService`
: Override the default URL for the SingleLogoutService for this
IdP. This is an absolute URL. The default value is
`/saml2/idp/SingleLogoutService.php`
: Note that this only changes the values in the generated
metadata and in the messages sent to others. You must also
configure your webserver to deliver this URL to the correct PHP
page.
`SingleLogoutServiceBinding`
: List of SingleLogoutService bindings the IdP will claim support for.
: Possible values:
* `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect`
* `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST`
: Defaults to HTTP-Redirect binding. Please note that the order
specified will be kept in the metadata, making the first binding
the default one.
`signature.algorithm`
: The algorithm to use when signing any message generated by this identity provider. Defaults to RSA-SHA1.
: Possible values:
* `http://www.w3.org/2000/09/xmldsig#rsa-sha1`
*Note*: the use of SHA1 is **deprecated** and will be disallowed in the future.
* `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`
`validate.authnrequest`
: Whether we require signatures on authentication requests sent to this IdP.
: Note that this option also exists in the SP-remote metadata, and
any value in the SP-remote metadata overrides the one configured
in the IdP metadata.
`validate.logout`
: Whether we require signatures on logout messages sent to this IdP.
: Note that this option also exists in the SP-remote metadata, and
any value in the SP-remote metadata overrides the one configured
in the IdP metadata.
### Fields for signing and validating messages
SimpleSAMLphp only signs authentication responses by default.
Signing of logout requests and logout responses can be enabled by
setting the `redirect.sign` option. Validation of received messages
can be enabled by the `redirect.validate` option.
These options set the default for this IdP, but options for each SP
can be set in `saml20-sp-remote`. Note that you need to add a
certificate for each SP to be able to validate signatures on
messages from that SP.
`redirect.sign`
: Whether logout requests and logout responses sent from this IdP
should be signed. The default is `FALSE`.
`redirect.validate`
: Whether authentication requests, logout requests and logout
responses received sent from this IdP should be validated. The
default is `FALSE`
**Example: Configuration for signed messages**
'redirect.sign' => true,
Shibboleth 1.3 options
----------------------
The following options for Shibboleth 1.3 IdP's are avaiblable:
`scopedattributes`
: Array with names of attributes which should be scoped. Scoped
attributes will receive a `Scope`-attribute on the
`AttributeValue`-element. The value of the Scope-attribute will
be taken from the attribute value:
: `someuser@example.org`
: will be transformed into
: `someuser`
: By default, no attributes are scoped. Note that this option also
exists in the SP-remote metadata, and any value in the SP-remote
metadata overrides the one configured in the IdP metadata.
Metadata extensions
-------------------
SimpleSAMLphp supports generating metadata with the MDUI, MDRPI and EntityAttributes metadata extensions.
See the documentation for those extensions for more details:
* [MDUI extension](./simplesamlphp-metadata-extensions-ui)
* [MDRPI extension](./simplesamlphp-metadata-extensions-rpi)
* [EntityAttributes](./simplesamlphp-metadata-extensions-attributes)
Examples
--------
These are some examples of IdP metadata
### Minimal SAML 2.0 / Shibboleth 1.3 IdP ###
'__DEFAULT__',
/* The private key and certificate used by this IdP. */
'certificate' => 'example.org.crt',
'privatekey' => 'example.org.pem',
/*
* The authentication source for this IdP. Must be one
* from config/authsources.php.
*/
'auth' => 'example-userpass',
);
simplesamlphp-1.15.3/docs/resources/ 0000755 0000000 0000000 00000000000 13245225037 016122 5 ustar root root simplesamlphp-1.15.3/docs/resources/simplesamlphp-googleapps/ 0000755 0000000 0000000 00000000000 13245225037 023136 5 ustar root root simplesamlphp-1.15.3/docs/resources/simplesamlphp-googleapps/googleapps-sso.png 0000644 0000000 0000000 00000025263 13245225037 026616 0 ustar root root PNG
IHDR U Bh iCCPICC Profile xڍ 3wϙ?3 ?- "" aQ,[zw+AA6nn)c]t9C)fu髼X4$́x^昨($@ruXvHD`J4GӃ6 D ] \f$>7B!Y744:d
L E! > R yU}nMFXj ppq89{Tҷ0"FBH@I$2GZ -#+'HSRVUS_g`hdlt,,m엯pXuOϵ^됹ni@ yаm1q;wڝ_&KޟzසIK?z2NgWVs9=_pWҲ+oܼUU};wox'-O={eWwOo_o
a81izf3 `p
b@8 U(]=}} PV6$0n(/(|1"
8~!8Ǖ9(ufơB@A Fj %!Bbu^ X)~)r1T
J
*0(@y`@"[B&W,(I^(xcURZ@YUG{
͏