Skip to main content

saml-auth

The saml-auth plugin enables API7 to act as the service provider (SP) and authenticate users via SAML 2.0 by interacting with identity providers (IdP).

Example

Integrate with Keycloak

The following example assumes you have installed API7 Enterprise locally and demonstrates how you can set up SAML single sign-on (SSO) with Keycloak.

Start a Keycloak Server

Start a Keycloak instance with admin username admin and admin password admin-pass:

docker run -d --name keycloak \
-e 'KEYCLOAK_ADMIN=admin' \
-e 'KEYCLOAK_ADMIN_PASSWORD=admin-pass' \
-p 8080:8080 \
quay.io/keycloak/keycloak:25.0.4 start-dev

Once started, visit http://localhost:8080 in browser to access the Keycloak admin console. Log in with the admin username and password.

Create a Client

Create a new client in Keycloak and configure the following:

  • Configure the Client type as SAML.
  • Enter the service provider's (SP) name as the Client ID, for example, api7.
    • Note that this value should be consistent with the sp_issuer parameter value, which you will configure later in the plugin.
  • Add http://127.0.0.1:9080/anything/login_callback to Valid redirect URIs.
  • Add http://127.0.0.1:9080/anything/logout_callback to Valid post logout redirect URIs.
  • Set Force POST binding option to Off.
  • Make sure the Sign documents option is On. Otherwise, SigAlg and Signature will be missing from the SAML response.

Find the Realm's SAML Metadata

In this step, you will find the idp_cert and idp_uri from the realm's SAML metadata file.

Select Real Settings and under the General tab, you should find SAML 2.0 Identity Provider Metadata in Endpoints. The metadata file should look similar to the following:

<md:EntityDescriptor
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="http://localhost:8080/realms/master">
<md:IDPSSODescriptor WantAuthnRequestsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo>
<ds:KeyName>wDDsXcgLGAZwZgpSb_jlBRf5MF8FoTcOYs0DgZ30Xcc</ds:KeyName>
<ds:X509Data>
<ds:X509Certificate>MIICmzCCAYMCBgGRl7njKjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjQwODI4MDY0MjA3WhcNMzQwODI4MDY0MzQ3WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdYPYSFoX2MADSIgfLYQ5oZcLNE+qB+qsO8sNpiebMQE3RmI5+MmZC/aozRzkzxcY+AoM50qfHrM1yM99A9ZxZt6fW/MuIv6IP5zWLDl0XWGVeOH0HIH4/xBxQetBxm1HdOYpCQg5Wm9hmYfebmN7NfW8HjnORjfUuUGgs5eCiHVqfiCfphLF5w+DcIcnjIwyF+xVH/7fRWgo5inBSeIavZh/LEv7LzBeRleGgoZ/+q7cVQiL2e0b8rsslqUOZJmwdPU3VSS0vW1bmXsZsfaZD0bgakFvSj0ARzwIbxc74eEQYKflHGS0zkrpm+TsO5KUn59SCPOhGNgGYpKKv6cY1AgMBAAEwDQYJKoZIhvcNAQELBQADggEBABN21PoEiTaZ20qQUdKD03m+bySlF4jRX2AeZqCedBaW+nHrbefaJdEnE9AcXBENCWVr6ntdeREaL9dW6KpV1hT4BmnXO2aiFotZe4Vc2W6cv7nDpjil6Q5/isbT5sriYhcU9oXBAaLf9dlg7K/X1l1+zcy9Pd1uKUfrC+5ds/Zv+xHiiK4h55o8shcmBmQ7bsanzNmjIQNnyF+lNRciGRvgJp59TR7AWpiBQDTNW1KK3XjO9lmN8nCEPbpdNGi77TDX0OZVrbbPy3vL4n8Gi3oQptHhmV7xou4fTEn9TCrdW82OLOduBCMk9t0tFFNB8Hlxq5XsLVLYW7O9GGcjDmI=</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8080/realms/master/protocol/saml/resolve" index="0"></md:ArtifactResolutionService>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8080/realms/master/protocol/saml"></md:SingleLogoutService>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8080/realms/master/protocol/saml"></md:SingleLogoutService>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://localhost:8080/realms/master/protocol/saml"></md:SingleLogoutService>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8080/realms/master/protocol/saml"></md:SingleLogoutService>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8080/realms/master/protocol/saml"></md:SingleSignOnService>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8080/realms/master/protocol/saml"></md:SingleSignOnService>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8080/realms/master/protocol/saml"></md:SingleSignOnService>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://localhost:8080/realms/master/protocol/saml"></md:SingleSignOnService>
</md:IDPSSODescriptor>
</md:EntityDescriptor>

Note down the certificate content in X509Certificate for plugin configuration idp_cert.

The SingleSignOnService.Location URL will also be used in the idp_uri plugin configuration later, where the localhost should be replace with your private IP address. For example, the idp_uri would look similar to http://192.168.2.101:8080/realms/master/protocol/saml.

Create Service Provider (SP) Certificate and Key

There are two approaches to create the service provider's certificate and key, and configure the certificate in Keycloak:

  1. Generate the certificate and private key locally using openssl, and import the certificate to Keycloak client; or
  2. Generate the certificate and private key in Keycloak, which automatically configures the certificate in Keycloak. You will save the certificate and private key for plugin configuration later in API7.

With the first approach, generate the certificate and private key using the openssl utility:

# Generate Private Key
openssl genrsa -out sp_private_key.pem 2048

# Generate Certificate Signing Request (CSR)
openssl req -new -key sp_private_key.pem -out sp_csr.pem -subj "/CN=API7"

# Generate Self-Signed Certificate
openssl x509 -req -days 365 -in sp_csr.pem -signkey sp_private_key.pem -out sp_cert.pem

In Keycloak, go to the client, and under Keys tab where you see the Client signature required option is set on On, you should see an option to Import Key for the Certificate. Choose Certificate PEM as the Archive format and import sp_cert.pem.

Alternatively if you wish to use the second approach, to generate the certificate and key in Keycloak, you can click Regenerate under Certificate. This will update the certificate configured in the client and download the private key to your host.

Create a Route with saml-auth Plugin

In API7 Dashboard, create a service called httpbin pointing to httpbin.org and add a route /anything allowing all HTTP methods. If you are not sure how to do so, see create service and route.

Next, add the saml-auth plugin to the route and use the following configuration.

{
"sp_issuer": "api7",
"idp_uri": "http://192.168.2.101:8080/realms/master/protocol/saml",
"login_callback_uri": "/anything/login_callback",
"logout_callback_uri": "/anything/logout_callback",
"logout_uri": "/anything/logout",
"logout_redirect_uri": "/anything/logout_ok",
"idp_cert": "-----BEGIN CERTIFICATE-----\nMIICmzCCAYMCBgGRl7njKjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0\nZXIwHhcNMjQwODI4MDY0MjA3WhcNMzQwODI4MDY0MzQ3WjARMQ8wDQYDVQQDDAZt\nYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdYPYSFoX2MADS\nIgfLYQ5oZcLNE+qB+qsO8sNpiebMQE3RmI5+MmZC/aozRzkzxcY+AoM50qfHrM1y\nM99A9ZxZt6fW/MuIv6IP5zWLDl0XWGVeOH0HIH4/xBxQetBxm1HdOYpCQg5Wm9hm\nYfebmN7NfW8HjnORjfUuUGgs5eCiHVqfiCfphLF5w+DcIcnjIwyF+xVH/7fRWgo5\ninBSeIavZh/LEv7LzBeRleGgoZ/+q7cVQiL2e0b8rsslqUOZJmwdPU3VSS0vW1bm\nXsZsfaZD0bgakFvSj0ARzwIbxc74eEQYKflHGS0zkrpm+TsO5KUn59SCPOhGNgGY\npKKv6cY1AgMBAAEwDQYJKoZIhvcNAQELBQADggEBABN21PoEiTaZ20qQUdKD03m+\nbySlF4jRX2AeZqCedBaW+nHrbefaJdEnE9AcXBENCWVr6ntdeREaL9dW6KpV1hT4\nBmnXO2aiFotZe4Vc2W6cv7nDpjil6Q5/isbT5sriYhcU9oXBAaLf9dlg7K/X1l1+\nzcy9Pd1uKUfrC+5ds/Zv+xHiiK4h55o8shcmBmQ7bsanzNmjIQNnyF+lNRciGRvg\nJp59TR7AWpiBQDTNW1KK3XjO9lmN8nCEPbpdNGi77TDX0OZVrbbPy3vL4n8Gi3oQ\nptHhmV7xou4fTEn9TCrdW82OLOduBCMk9t0tFFNB8Hlxq5XsLVLYW7O9GGcjDmI=\n-----END CERTIFICATE-----",
"sp_cert": "-----BEGIN CERTIFICATE-----\nMIIC0TCCAbmgAwIBAgIUAT7h3zLAul/3S1F9Ms9w7JjpoJ0wDQYJKoZIhvcNAQEL\nBQAwETEPMA0GA1UEAwwGQVBJU0lYMB4XDTI0MDgyNzA5MDk1NloXDTI1MDgyNzA5\nMDk1NlowETEPMA0GA1UEAwwGQVBJU0lYMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\nMIIBCgKCAQEAvJBsuNfgvxe+xrBPr9+OCwD4dk3M9ua+14l9tlQHFgtqGXEq7nYc\n0ic9wqim+kdxpJWfiwG0mClklO0nELNsgBVrC06FqrcSe2CGEh91UBkGEOzvOgm7\nEBJOB/5Nc4tE/3NXM0ocfRgFXNEvGMkH9M+odGk7ZQraI/hfazwYgjOty1LrvSMp\nKhCfx0DpKlLuX0w2P9CfLuSgZ0ZTdN3Yr4icEuEs0i3ptCd/bip2fccKkRWEguIe\nywoDl/2fjubJFc5sFhl7Rtf+CeFKgqeByNPX2+UCix136L1r+VIlA+3ClInPWZUY\nWCbs/envBO6omUsnqPPCU2zVdYW0Qb+rrQIDAQABoyEwHzAdBgNVHQ4EFgQUvGIj\nuvPoHC74lhKSlOJAwrdq4WwwDQYJKoZIhvcNAQELBQADggEBAJU0+aKCUSYvN6oe\n7PHYD0ZvE13wItzKq/7DQQe1zA/kDoCvSyC8+gB+FZmdHmkGGNdNqXsQgHEnP7Y0\nx7gDqA3s0blXEkECfmmRcVxcS3rb8CVVFqiKdyRO91opdir5J9vbmiF7RK1ajFTy\nyemhK0xxFpPM+gTdetEj7AoVMrlRoOLC+L62GaSi/gpQmKPR91FLyj33vCfVrDCo\nQXYMPQmSbBCwlHrHWa/Px7F7aQ3fuwmY6jgObxewl3HUSCfV1TT4/uYV9GsrVx4p\np9LcyuVBuJroIlCJrk5Q/ozGhuiRoKApaTeUSjy5opziBRC2bF+TIxbO9Mkibtbh\nxvXZ4WE=\n-----END CERTIFICATE-----",
"sp_private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC8kGy41+C/F77G\nsE+v344LAPh2Tcz25r7XiX22VAcWC2oZcSrudhzSJz3CqKb6R3GklZ+LAbSYKWSU\n7ScQs2yAFWsLToWqtxJ7YIYSH3VQGQYQ7O86CbsQEk4H/k1zi0T/c1czShx9GAVc\n0S8YyQf0z6h0aTtlCtoj+F9rPBiCM63LUuu9IykqEJ/HQOkqUu5fTDY/0J8u5KBn\nRlN03diviJwS4SzSLem0J39uKnZ9xwqRFYSC4h7LCgOX/Z+O5skVzmwWGXtG1/4J\n4UqCp4HI09fb5QKLHXfovWv5UiUD7cKUic9ZlRhYJuz96e8E7qiZSyeo88JTbNV1\nhbRBv6utAgMBAAECggEAFPBeulnykZXD8BFVD/0dq1gkvxJdn884wvt4E76Z+Nc0\npXWdJFTGV4nXAF41CJbVZkbdLBT45mq2ShlZnK+n7UMzm1JRYocozL2Htcx7fPUC\naO++ku3QsXSu6JFTLXD6LPm0ZbQlnLiFo+xws+pi8Ur79E1ZNJuzZIooomJOgGqm\nz/0aTCw1JbMXAI7x0ygCYarfhqX4/M6qokV0Nt64hHxHxtrIWzVac+1QdR4WLaFL\nbdrb6QQeeCw5rWUrZfqmF6+NwCCeP5k/HMeVSwXsI+WrEVCjQBB2qpFqgiDNyfz2\n2i7UYXBP0PUmHEPsctWCYlWwqskBxLZnJdDKTmBCKwKBgQDpXpUpNgaI1LOrhxEQ\n5v1iXDSJweV8Kcdth+e6IGFLtxBgvhDNCijBhwKaFe90SFRldGQgZrz4tBKcxdEw\nslGbbNSSmVZ7nSMpZQoV74Uyrk2i7vxq6A9+ZCMWFpFIwoFBz4SUpnwEe+TEe/l3\nAMOz8BdFa3J0XzUhL7k5X+KaewKBgQDO2Yvi84JhwcmgRzlhv5o6gD40C5x1dv5w\nRqnXxnZGigVwtSBS6CoayBtL8MYNdTB5oM6qoF/FiVHYxbnwgD3d4net/BbUYz9H\nkONxwuEM0a35uSf2FHCaRn7BDPjmbdNmrkWr0bHyjlNAd1CQiwmeLxnaTwjf3C+M\nTdI+p08t9wKBgDms84Zk4MaOcv0we2pG/FaD3UQylInUNYJ/dSjN+d3hl32hW7uh\nCCOUP3NfenetrJYKZviPC6MXtgXi6el0GLEl+39jwDj6xAbl/tEfCjdVVsCu+dle\nEv40t2stFqj50UI3jFfEsZ/WEtrwnN3pZXSiIM46WOYj5ZiXF9rzNKjjAoGBAJcv\nwKPf8fM7rgA9Lr64SaTqqQxnVDMzByPPMkKpJzfFl9ZaPMb8NBIhInpuAIRDnGu5\n0nQ6BeYeyTjUxGP5h76O0YTUVWdlJxJK30L9+nnhI/T7lS6yn97TGcBGmAHsUfCh\n/gBoo1SzHDxpOPR8+0moCZBb5hOhHwvAsaPjq+bfAoGBALV/t+smBLogJOBXpfKU\n9LCXnnIqG804vyobSNCVoJm832gBTM7fVcTZa5I+0O+l1emEETIgKU+5ioP/qwou\nU3a/7jXX4hewCpmPVhvvlHgjs+UOBS6hXQMnq52h6mPhiikGOQ6YnqHtxyFORIlo\ntUlwMjanVlxRKyGJlBYQtADk\n-----END PRIVATE KEY-----"
}
tip

Replace the idp_uri IP address, idp_cert, sp_cert, and sp_private_key with your own values.

Click Save to save the configuration.

Verify

Navigate to http://127.0.0.1:9080/anything/saml-test in your browser and log in with your Keycloak credentials.

If successful, you should be redirected and see a response similar to the following in your browser:

{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-CA,en-US;q=0.9,en;q=0.8",
"Cookie": "saml_session=90f84a61-cb03-4f8c-8202-5e7b5267bda6",
"Host": "127.0.0.1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15",
"X-Amzn-Trace-Id": "Root=1-66cf4d36-18bbacc80af8987b77b1f5c4",
"X-Forwarded-Host": "127.0.0.1"
},
"json": null,
"method": "GET",
"origin": "192.168.65.1, 203.91.85.123",
"url": "http://127.0.0.1/anything/saml-test"
}

API7.ai Logo

API Management for Modern Architectures with Edge, API Gateway, Kubernetes, and Service Mesh.

Product

API7 Cloud

SOC2 Type IIISO 27001HIPAAGDPRRed Herring

Copyright © APISEVEN Ltd. 2019 – 2024. Apache, Apache APISIX, APISIX, and associated open source project names are trademarks of the

Apache Software Foundation