LinOTP integration for SimpleSAMLphp | by Greg Harvey

linotp integration simplesamlphp 2fa saml mfa setup sso security
D
Daniel Wright

Technical Writer & IAM Specialist

 
February 13, 2026 7 min read
LinOTP integration for SimpleSAMLphp | by Greg Harvey

TL;DR

  • This guide covers how to plug LinOTP into your SimpleSAMLphp setup to get that sweet multi-factor authentication going. You'll learn about authproc filters, configuring the linotp api, and making sure your saml assertions are actually secure. We also look at common pitfalls when dealing with identity providers and how to test your config without losing your mind.

Why bother with LinOTP and SimpleSAMLphp?

Ever tried explaining to a ceo why a six-digit password isn't enough anymore? It's like trying to stop a flood with a paper towel, honestly.

Passwords are basically a "please hack me" sign for modern attackers. If you're running a portal for healthcare or even just a retail backend, you need layers.

  • Security is a moving target: A 2024 report by Verizon found that over 60% of breaches involved compromised credentials, which is just wild.
  • LinOTP is the secret sauce: It's an open-source backend that handles otp tokens without locking you into one vendor.
  • simplesamlphp is the glue: It's still the go-to for connecting different apps because it just works with almost any federated identity setup.

Diagram 1

In practice, a finance firm might use this to bridge their legacy api with modern saml. It keeps things tight without breaking the bank on licenses.

Next, we'll dive into getting the actual bits installed.

Getting the Software on the Box

Before we talk config, you actually need the code on your server. For LinOTP, if you're on Ubuntu, you're usually adding their repository and grabbing the packages.

# Add the LinOTP repo and install
add-apt-repository ppa:linotp/stable
apt-get update
apt-get install linotp2 linotp2-adminclient-cli

For simplesamlphp, you usually just download the tarball or clone it into /var/simplesamlphp. You'll also need to point your web server (like apache or nginx) to the public directory so it actually loads.

The most important part for our integration is getting the specific linotp module. Don't just download random zips; use composer in your simplesamlphp directory:

composer require pulsesecurity/simplesamlphp-module-linotp

This pulls in the logic needed to talk to the linotp api without you having to write custom php from scratch.

Setting up the LinOTP side of things

So, you got the software installed but now comes the part where most people start pullin' their hair out—actually making LinOTP talk to your users. If LinOTP doesn't know who your users are, it can't exactly give them a token, right?

The UserIdResolver is basically the bridge between linotp and your user database. You usually set this up in the LinOTP Management Web UI under the "LinOTP Config" -> "UserIdResolver" tab. You'll define your connection string there. For example, an LDAP resolver might look like this in the backend config:

ldap.uri = ldap://localhost, ldap.binddn = cn=admin,dc=example,dc=com

  • Connect to your source: You'll need to define if you are using LDAP, SQL, or even a flat file. Most enterprise setups go with LDAP because it's just easier to manage at scale.
  • Create a Realm: Think of a realm as a logical container. You might have one realm for "Healthcare_Staff" and another for "Contractors" to keep things organized.
  • Test with curl: Don't just hope it works. Use a simple api call to see if the resolver actually sees your account.

Here is a quick example of how you'd check a user status using the api via terminal (make sure you use the right parameter name!):

curl -k https://localhost/admin/show?user=greg.harvey&resolver=my_ldap_resolver

It's also worth noting that complexity is a huge barrier. A 2023 report by Thales found that 55% of IT professionals see it as a top reason for mfa deployment failing. Keeping your resolvers simple helps avoid that mess.

Diagram 2

Next, we're gonna look at how to actually link this up to simpleSAMLphp so the login flow actually completes.

SimpleSAMLphp Configuration and Authproc Filters

Now that LinOTP knows who your users are, we gotta make simpleSAMLphp actually ask for that second factor. It’s honestly not as scary as it sounds—you’re basically just dropping a specialized filter into your auth chain.

Important Note: The "authproc" filters don't work in a vacuum. You first need a primary authentication source defined in config/authsources.php (like an LDAP bind). The filter only runs after the user has successfully logged in with their first password.

Once your primary auth is working, you need to enable the module in your config/config.php by making sure 'linotp' is in the module.enable array.

The real magic happens in your metadata/saml20-idp-hosted.php (or your config.php if you want it global). You’ll add an authproc filter. This is just a fancy way of saying "hey, before you finish logging this person in, run this extra check."

  • Set the parameters: You need to tell the filter where your LinOTP server lives (the api url).
  • Attribute Mapping: This is where things usually break. You have to ensure the username simpleSAMLphp got from your primary auth (like LDAP) matches the "User" LinOTP is looking for.
  • SSL stuff: If you're using self-signed certs in a lab, you might need to toggle ssl_verify to false, but please don't do that in production, okay?

Here is a basic look at what that filter config looks like:

'authproc' => [
    10 => [
        'class' => 'linotp:OtpFilter',
        'linotp_url' => 'https://linotp.example.com/validate/check',
        'ssl_verify' => true,
        'username_attribute' => 'uid',
        'realm' => 'Healthcare_Staff',
    ],
],

I've seen so many retail setups fail because the IdP sends email but LinOTP expects sAMAccountName. If they don't line up, LinOTP just shrugs and says "user not found," and your login loop begins.

As that Thales report mentioned, complexity is a killer for these projects. Getting these attributes right the first time saves you a massive headache later.

Diagram 3

In a high-stakes environment like a hospital system, you might even add logic to only trigger this for certain "sensitive" apps. It keeps the doctors happy because they aren't typing codes just to check the cafeteria menu.

Testing and Validating your SSO Flow

It's one thing to see your config file look pretty, but it's another to actually see a login work without blowing up in your face. I can't tell you how many times I've walked away from a "finished" setup only to get a frantic Slack message ten minutes later because someone in the retail branch can't sync their scanner.

To really see what's happening under the hood, you need to look at the actual saml assertions being passed back and forth. Tools like the SAML Tracer extension for Firefox or Chrome are absolute lifesavers here.

  • Watch the Redirects: You want to see the user hit simpleSAMLphp, get kicked to the OTP page, and then finally land at the app with a valid signature.
  • Check the Attributes: Make sure the eduPersonPrincipalName or uid matches exactly what LinOTP saw during the test we did earlier with curl.
  • Timestamp drift: If your server clocks are off by even a minute, the assertion will fail. Use ntp to keep things synced up.

If you're seeing a "State Lost" error, it usually means your session cookies are fighting each other or you've got a load balancer misconfigured. Since complexity stalls these rollouts, keep your testing environment identical to production to catch these quirks early.

Security Best Practices and Final Thoughts

Look, you can have the fanciest mfa setup in the world, but if you leave your api keys sitting in a public git repo, you’re basically handing the keys to the kingdom to any script kiddie with a scanner. it happens more than you'd think in fast-paced retail or healthcare dev cycles.

First rule of fight club: don't hardcode secrets. Use environment variables or a proper vault. If you're putting your LinOTP admin password directly into authsources.php, just stop.

  • Environment Vars: pull your sensitive strings from the system.
  • Log Monitoring: setup alerts for "500 Internal Server Error" or repeated failed 2fa hits. If a finance app suddenly sees 200 failures from one ip, you've got a problem.
  • Stay Updated: simpleSAMLphp puts out security patches for a reason. Don't be that person running a three-year-old version because you're "scared to break the theme."

A 2023 report by IBM found that the average cost of a data breach reached $4.45 million, so yeah, those patches are worth the ten minutes of downtime.

Diagram 4

Anyway, the goal here isn't just to "check a box" for compliance. It’s about making things hard enough that attackers go look for an easier target. When you combine the flexibility of LinOTP with the reliability of simpleSAMLphp, you’re building a pretty solid wall.

Just remember to keep testing. Use those tools we talked about earlier and don't assume "no news is good news." Stay safe out there and keep those tokens rotating.

D
Daniel Wright

Technical Writer & IAM Specialist

 

Daniel is a London-based identity access management expert who translates technical SSO concepts into clear, actionable content. He has consulted for multiple UK-based tech firms on IAM architecture.

Related Articles

SAML Protocol - IT Security & Risk Documentation
SAML protocol

SAML Protocol - IT Security & Risk Documentation

A complete guide for it professionals on SAML protocol security, risk documentation, and sso configuration best practices for enterprise technology.

By Daniel Wright February 11, 2026 7 min read
common.read_full_article
SAML web application toolkit: Single sign-on to a ...
SAML toolkit

SAML web application toolkit: Single sign-on to a ...

Learn how to use a SAML web application toolkit for single sign-on. Expert tips on sso configuration, idp testing, and security best practices for IT pros.

By Daniel Wright February 9, 2026 6 min read
common.read_full_article
Is SAML still relevant today?
SAML relevance

Is SAML still relevant today?

Explore if SAML is still relevant for modern SSO configuration. Compare SAML vs OAuth, learn security best practices, and see why it stays vital for enterprise tech.

By Daniel Wright February 6, 2026 8 min read
common.read_full_article
4. System config — LinOTP 2.7 documentation
LinOTP 2.7 system config

4. System config — LinOTP 2.7 documentation

Deep dive into LinOTP 2.7 system configuration. Learn about failcounters, SAML attribute returns, TOTP timesteps, and security best practices for SSO.

By Daniel Wright February 4, 2026 6 min read
common.read_full_article