make sure SLO URL is registered
update fkooman/jwt
simplify code somewhat
Simple SAML 2.0 IdP and OpenID Connect OP.
DO NOT USE
This is very much a work in progress. Do not use (in production) before a 1.0 release!
xmlseclibs
pairwise-id
) supportAuthnRequest
and LogoutRequest
signatures if SP public key is
known/.well-known/openid-configuration
supportnonce
parameter be sent with the "authorization request"RS256
) used to sign the "ID Token", does not seem EdDSA is
supported by anyoneuserinfo
endpoint supportacr_values
query parameter support for 2FA
We tested with:
Git clone the repository. Use Composer to install the dependencies:
$ git clone https://git.sr.ht/~fkooman/php-saml-idp
$ cd php-saml-idp
$ composer update
$ cp config/config.php.example config/config.php
Modify config/config.php
to configure the IdP.
Generate secrets:
$ php libexec/generate-secrets.php
$ mkdir config/keys
$ openssl req \
-nodes \
-subj "/CN=SAML IdP" \
-x509 \
-sha256 \
-newkey rsa:3072 \
-keyout "config/keys/saml.key" \
-out "config/keys/saml.crt" \
-days 3600
$ make dev
Then go to http://localhost:8080/
.
$ php bin/add-user.php
User ID: foo
Setting password for user "foo"
Password:
Password (repeat):
By default the uid
attribute is created for the newly created user set to
the "User ID".
Once you add your first user you can make it "Admin" by adding the User ID to
adminUserIdList
in config/config.php
. Afterwards you can manage your
account and additional users through the web interface.
$ php bin/add-attribute.php
User ID: foo
Attribute Name: eduPersonEntitlement
Attribute Value: https://eduvpn.org/expiry#P1Y
Or use the web interface if you prefer.
$ php bin/add-otp.php
User ID: foo
OTP Secret: ZJDLQWPRG44QNCFTWMDZOXIHJI5LASWR
Provide OTP key: 587196
otpauth://totp/fralen-tuxed-net:foo?secret=ZJDLQWPRG44QNCFTWMDZOXIHJI5LASWR&algorithm=SHA1&digits=6&period=30&issuer=fralen-tuxed-net
Using CLI tooling you can generate an OTP use oathtool
like this:
$ oathtool --totp -b ZJDLQWPRG44QNCFTWMDZOXIHJI5LASWR
587196
This is not yet possible through the web interface.
To configure mod_auth_openidc
use the following:
OIDCProviderMetadataURL https://idp.example.org/.well-known/openid-configuration
OIDCClientID q9ZduFZHNUIFjWG8
OIDCClientSecret fKUsLWQIL7sRVoo5
OIDCRedirectURI https://rp.example.org/app/redirect_uri
OIDCCryptoPassphrase sV4OIiIeO7QZ748beMWaAH1G421jfXET87TGdGJtoHs9jHfo3upxAWRgpZ9bIWH0
# if you want to use e.g. preferred_username as identifier in the RP, you need
# to request the `profile` scope
OIDCScope "openid profile"
OIDCRemoteUserClaim preferred_username@
#OIDCPKCEMethod S256
# if you want to request 2FA from the OP
#OIDCPathAuthRequestParams "acr_values=https://refeds.org/profile/mfa"
<Location /vpn-user-portal>
AuthType openid-connect
<RequireAll>
Require valid-user
#Require claim acr:https://refeds.org/profile/mfa
</RequireAll>
</Location>
NOTE: update the values as required, make sure to generate your own
OIDCCryptoPassphrase
, e.g. using pwgen -s 64 -n 1
.
Use php-saml-idp-add-client
to configure a new RP. You'll need to provide a
redirect_uri
and a "Display Name". The client_id
and client_secret
are
generated.
$ php bin/add-client.php
Display Name: My Test RP
Redirect URI: https://rp.example.org/callback
Client ID : 3c3dbb8972aad7dfbd358bf2757d0848
Client Secret: 82fa0e9e0d5a9a28a60ad19e8edbbdf4
Display Name : My Test RP
Redirect URI : https://rp.example.org/callback
You can also use the web interface to register/update/delete RPs if you make
yourself an "admin" by adding your user ID to adminUserIdList
in the
configuration file, e.g.:
'adminUserIdList' => ['foo'],
If you want to be able to use Webfinger, you can host this file on the domain
you want to use, e.g. on https://tuxed.net/.well-known/webfinger
. It can be
a static file. The Content-Type
MUST be application/jrd+json
. Make sure you
point href
to the OIDC IdP URL.
{
"links": [
{
"href": "https://idp.tuxed.net",
"rel": "http://openid.net/specs/connect/1.0/issuer"
}
]
}
For Apache you'd use something like this to set the Content-Type
for a static
file:
<Location "/.well-known/webfinger">
Header set Content-Type "application/jrd+json"
</Location>
Tested on Fedora 38.
Repository Key:
# rpm --import https://repo.tuxed.net/php-saml-idp/v1-dev/rpm/fkooman+repo@tuxed.net.asc
Repository Config:
$ cat << 'EOF' | sudo tee /etc/yum.repos.d/php-saml-idp_v1-dev.repo
[php-saml-idp_v1-dev]
name=Repository for php-saml-idp
baseurl=https://repo.tuxed.net/php-saml-idp/v1-dev/rpm/fedora-$releasever-$basearch
gpgcheck=1
enabled=1
EOF
$ sudo dnf -y install php-fpm httpd mod_ssl php-saml-idp
$ sudo systemctl enable --now php-fpm
$ sudo systemctl enable --now httpd
Generate keys:
$ sudo /usr/libexec/php-saml-idp/generate-secrets
Fix permissions (as root):
TODO: fix permissions on directory with sticky bit
# chmod 0644 /etc/php-saml-idp/keys/*
Generate SAML keys:
$ sudo mkdir /etc/php-saml-idp/keys
$ sudo openssl req \
-nodes \
-subj "/CN=SAML IdP" \
-x509 \
-sha256 \
-newkey rsa:3072 \
-keyout "/etc/php-saml-idp/keys/saml.key" \
-out "/etc/php-saml-idp/keys/saml.crt" \
-days 3600
...
Fix SELinux to allow LDAP connections:
$ setsebool -P httpd_can_connect_ldap=on
You should now be able to visit http://host/php-saml-idp/
.
Install certbot
to configure HTTPS:
$ sudo dnf -y install certbot
$ sudo systemctl stop httpd
$ sudo certbot certonly
Modify /etc/httpd/conf.d/ssl.conf
to point to the chain and key.
$ sudo systemctl start httpd
TODO: document auto renew TLS certs using certbot
.
isMemberOf
as groups
?