Creative Use of OpenID
The Situation
I have three websites that all used to be the same one. As a result, they use a single database for user administration and authentication. Unfortunately, they are very distinct websites and have grown to include drastically different features.
When all three sites were just one site, we used a nifty layout switcher that keyed on the requested URL to determine which stylesheets to use. But if you logged in to domain1.com
with a user from domain2.com
, the server would just swap the URL for you without a problem.
As we added features to one site, we needed to split the three into different systems to keep from stepping all over ourselves. Adding a feature to domain1
would break an unrelated system on domain3
, so keeping things separate was smarter. But we kept the same user database because it's tied in to our licensing and subscription systems.
Now, we want to begin using SSL/TLS to protect the sites ... meaning they're transferred over HTTPS rather than HTTP.
Using HTTP, we didn't have too many problems bouncing users from one site version to another. You could log in to any of the three sites, the server would detect which site you were supposed to be on, and would kick you over there. Since we're using a State Server for session management, you didn't lose anything in the transfer, either (same 开发者_运维技巧user database, same session ID, same session).
Using HTTPS, we lose this when we kick users from one site to another. At the moment, the best we can do is display a pop-up and explain "You meant to log in to domain2.com
... please update your bookmarks and log in again" before kicking them to the right domain. This works, but it's an inelegant solution, frustrates the end users, and it really just sloppy.
Ideal Solution
Ideally, users would be automatically logged in to the site they're being transferred to once they get there. So:
- Log in to
domain1.com
with a user account fromdomain2.com
- Get a popup explaining your mistake and asking you to update your bookmarks
- Be automatically transferred to
domain2.com
and logged in as if you'd gone there to begin with.
Original Approach
The first idea we had to accomplish this was to redirect the user and append an ID of some kind to the URL and fetch the appropriate GET parameter when they get to the new site. While this works and we can log people in ... it's very insecure. You're basically creating a token anyone could use to authenticate as that user and passing it over the wire where it could be intercepted and impersonated.
OpenID Approach
What I'm thinking now, and I'm not even sure it will work (hence the question), is to use some variation of OpenID. Both domain1.com
and domain2.com
are on our servers, under our control, and using our SSL certificates. We have full access to the database and, once we know which session to restore, can restore a user's session once logging them back in after the site redirect.
When I've used OpenID in the past, it's taken this format:
- Go to Site A I want to use and click Log In
- Be redirected to the login page for Site B, where I already have an account
- Log in to Site B and grant permission for Site A to use my information
- Be redirected to the authenticated portion of Site A
I want our system to replicate steps 3-4 of that process. Basically:
- Go to
domain1.com
and log in (you already have an account) - Read a message about fixing your bookmarks and click OK to be redirected to the right site.
- Be redirected to the authenticated portion of
domain2.com
From what I've ready about OpenID thus far, this seems possible. And I've been reading up on OpenID and OAuth for a couple of days now to figure this out. But every solution, tutorial, and manual I can find describes a fully-fleshed-out OpenID server. We don't need people to use external OpenIDs to authenticate to our system, and we don't want to become an OpenID provider either. We just want to create a solution that works following the above description.
So, is this possible using OpenID? Which parts of the protocol will we need to flesh out to make it work?
You don't necessarily need OpenID to log the user simultaneously into multiple domains. You can just generate a "signed redirect" from domain1.com to domain2.com with an "assertion" as one of the parameters on the url to domain2.com
The assertion should contain the userid, a timestamp, and a signature generated using a shared secret between domain1 and domain2. In order to prevent replay attacks, domain2 should verify that the timestamp is relatively recent (10 minutes). The signature should be generated by hashing the assertion with the shared secret. The signature enables domain2 to verify that domain1 generated the assertion, assuming that the shared secret is only known between domain1 and domain2.
At a high level, the mechanism I described is equivalent to generating an "unsolicited assertion" in the SAML world. Unsolicited assertions are theoretically supported in OpenID, but I've never seen it implemented in practice.
If you haven't implemented this sort of Single Sign On (SSO) technique before, you should be very careful, as incorrect implementations can potentially allow attackers to login to domain2 as any user.
精彩评论