Search code examples
phpsecurityencryptionaccess-token

One-time login tokens for third-party access to a resource


We have a website (foo.com) that does online training. A user logs in, then completes their training.

We've agreed to allow another company (bar.com) to send their clients through our training. One of the requirements is that their users should not need to create a separate login account on our site.

Here is my initial plan of attack:

  1. When a user logs into bar.com (the other company's website), their backend will make a secure HTTPS request to foo.com (our website) requesting a one-time access token specifically for that user. For example, they may request the following URL:

    https://foo.com/api/request_token.php?user=bob&pass=A1B2C3D4E5F6

    This requests access to bob's account. The 'pass' component is a shared passkey known by foo.com and bar.com that is used to verify that the request is legitimate.

  2. foo.com will respond with a one-time access token (for example, 0123456789ABCDEFG) which is stored into a database along with the user's id (bob).

  3. bar.com will present a hyperlink to the user that links back to the online training at foo.com. Something like this:

    https://foo.com/api/login.php?user=bob&token=0123456789ABCDEFG

  4. When the user clicks on the link, foo.com checks the token in the database and (if it has not expired) removes it from the table of valid tokens and creates a session variable indicating that bob is now logged in, then redirects him to the training.

What I'd like to know is, where are the security holes and how can I mitigate them? I know that the URL will be encrypted, and I know that an entry will show up in my server log, but it's a one-time token, so I'm not worried about that. I can imagine someone brute-forcing different tokens, so I've included the user name in the second login url that the user clicks on so that the token will only work with that specific account.

But what I'm really worried about is what I don't know. And I don't understand much about the security issues here.

(Please note that this only covers an existing user who is attempting to log in. I will use another method to actually create the user account on foo.com)

I am coding in PHP.


Solution

  • What you're looking for is known as single-sign-on (SSO). There are a number of different industry-standard protocols for achieving this, but what you're basically doing is having another entity authenticate the user and provide that information to you in a way that you can verify that something you trust (their authentication system, whatever it is) has issued it.

    The most standard way of doing this is SAML (Security Assertion Markup Language). This is a protocol where the third-party would authenticate to their system and it would generate a SAML Assertion that basically says who the user is (and other information, should that be required). The assertion is digitally signed so you can verify who issued it. This requires that you and the third-party exchange keys (in the form of certificates) and come to an understanding about what your assertions will contain, etc (typically expressed in SAML metadata that is exchanged between the Identity Provider and the Service Provider).

    There are a number of SAML implementations/references out there for many platforms, including PHP. If you want to do this right, and securely, that is what you should investigate and pursue.