How to create a Shared Login Service across Multip

2019-01-16 06:09发布

问题:

I'm interested in how to implement a shared cross-domain login system as well as best practices and security precautions to take. If you are familiar with 37Signals, you are probably accustomed to their usage of having a shared universal authentication mechanism whereby you do not have to subsequently login if you use the top level navigation to a different product. I would like to implement something in a similar fashion.

The closest thing I've found online is the Wikipedia entry on a Central Authentication Service and the response to Cross Domain Login - How to login a user automatically when transfered from one domain to another, which may be slightly different in this case.

I have inspected their session cookies to get a grasp on what they're doing in the process. Initially, each product link has a "goto" uristub, i.e.:

https://MY_COMPANY.campfirenow.com/id/users/[int_identifier]/goto

Using FireCookie and the NET tab in Firebug, I'm able to see the cookies that are set and the redirects that occur in the process. The goto url fires a 302 redirect to:

https://MY_COMPANY.basecamphq.com/login/authenticate?sig=[BASE64_ENCODED_AND_ENCRYPTED_DATA]

The session identifier is recreated, most likely for CSRF purposes. Some of the data in the cookies as well as the GET parameter sig were partially decrypted using base64_decode to the following:

// sig GET param
array(2) {
  [0]=>
���ף�:@marshal_with_utc_coercionT7�z��<k��kW"
  [1]=>
  string(18) "���k�<kn8�f���to��"
}

// _basecamp_session cookie session param
string(247) {
:_csrf_token"1Sj5D6jCwJKIxkZ6oroy7o/mYUqr4R5Ca34cOPNigqkw=:session_id"%060c0804a5d06dafd1c5b3349815d863"
flashIC:'ActionController::Flash::FlashHash{:
@used{: auth{"
              MY_COMPANY{:
                       user_idi�3
:identity_idi�W����������s�]��:�N[��:

߾�����"

The encoding is breaking the code block. Thanks for your help!

回答1:

I think the key in your Q is where you write "whereby you do not have to subsequently login if you use the top level navigation to a different product".

I will explain: You want to be able to move from site1.com to site2.com and let site2.com know that you are some user that logged in via site1.com.

because cookies are not shareable between different domains (other then subdomains but I guess you are not talking about sub-domains) you have to pass some information on the link to site2.com that will let it talk with its back-end and know what user you are.

lets start with a naive solution and then work our way to make resolve some of the problems that it poses: suppose you have a users table on some back-end DB and your user has some ID. now assume that the user authenticated on site1.com and he is user 123 from your DB. The most naive solution would be to call site2.com/url/whatever?myRealID=123 and have site2 check for this ID and "belive" the user that this is indeed him.

Problem: Anyone (even a valid user of your site) that will see your link can create a link with myRealID=123 or try other values for it. and site2.com will accept him as that user.

Solution: lets not use guessable ID's suppose you add to your users table a unique GUID and if user 123 has a guid of 8dc70780-15e5-11e0-ac64-0800200c9a66 then call site2.com/url/whatever?myGuid=8dc70780-15e5-11e0-ac64-0800200c9a66.

New Problem: well even though It would be very unlikely that someone will guess your user's GUID his GUID can still be hijacked by some middle man that sees this link and it someone will get the guid he can use it for ever.

Solution: Use a private key saved on your server to sign a string that contains the following data items, current time-stamp, destination site (i.e "site2.com") the said GUID, this signature can be translated into saying "This is a proof that this link was created by the site at the said time for the user that has this GUID to authenticated by this domain" and send it to site2.com along with the time-stamp and GUID. Now when site2.com gets the link he can make sure that it is signed properly and if some middleman or originally user would try to change it in any way (either my modifying the time or GUID) then the signature would not match and site2.com will refuse authenticating the user.

One last problem: if the link is intercepted by a middleman he can still use if from some other machine.

Solution: add a nonce to the passed parameters. The nonce is just a random number that your authentication system should make sure that it does not allow you to authenticate with this number more then once (hence then name N(umber)-ONCE). Note that this means that each link you create on site1.com that leads to site2.com should have a distinct nonce which needs to be saved on the back-end for later validation.

because you don't want to keep adding records to this nonce table forever it is custom to decide that such a link is only valid for some given time after its creation. and so you can create nonce records that are older than this time limit.

I hope that this is the outline you where looking for. It is possible that I missed something but those are the basic guidelines, use a signature to prove the authenticity of the data in the link and use a nonce to prevent middleman attacks. I would also recommend using HTTPS for those links if possible.

Eyal



回答2:

You could try to implement a Global Network Auto-Login solution à la Stack Overflow.
There's an insightful post regarding its brilliant implementation by Kevin Montrose here.

It would require Cookies, HTML5 localStorage, Javascript, Iframe and a lot of security checks but I think it's worth it.



回答3:

Allowing users the option of using their facebook/yahoo/gmail/openID solution is a start, but that doesn't ulimately solve the solution of implementing or using one's own solution.

Having developed and managed an implementation in the past (we ultimately went toward SiteMinder, but I'm guessing you don't want the cost of a real product), I think that Eyal has a very good idea, but I'd add a little tweak to it.

At the time of authentication, generate a random code (could be a GUID value, but it is not static per user) that is stored in a transactional table along with the user id. This code has a maximum lifetime (you'll need to judge the safety value for that time period). This code would ideally be either hashed with the user name or encrypted and sent across as part of the URL.



回答4:

Have you tried something like Charles to sniff what is being sent back and forth? It might be able to break down things further for you.

As mentioned by FlipScript, perhaps using OAuth/OpenID might be a way forward for you?



回答5:

Take a look at Jasig CAS http://www.jasig.org/cas . I think it will do what you want. It's open source, and has a number of plugins to allow you to authenticate use multiple sources of authentication and from multiple domains/languages.



回答6:

Use Something Like .NET Passport (IE. Windows Live Id) Or The Way Facebook Has Done It With Their API, Which Can Be Openly Viewed.



回答7:

Why no use Open ID for this purpose.

OperID will be the optimum solution for this problem.