single sign on between Vbulletin and rails applications - ruby-on-rails

we have a lot of users on a VBulletin forum. now i want write few more apps on rails for the same userbase. Until now all the authentication and session management is being taken care of by VBulletin. What is the best way to provide SSO for my users both onVBulletin and on the rails apps i am writing
I am working on single sign-on process with v Bulletin and custom made application. i can logged in at Vb using cookies. i can access all. but when access send "Private Message". it says
"
You have turned off private messages. You may not send private messages until you turn them on by editing your options.
"
is there all permission are set at "datasource" table?..
Thanks
master

Ideally your two sites are subdomains of a common domain (e.g. forum.example.com and rails.example.com), or share the same domain (www.example.com.) One of the sites would be the primary authenticator, and set a cookie (for .example.com in the case of the common parent domain [notice the . before example.com] or www.example.com in the case of the shared domain, so that both applications can access it), where the cookie contains:
the user ID
a salt (random value calculated at login time), and
a SHA-2 signature computed over the triplet (user ID + salt + a shared secret key), where the shared secret key is a secret string known by both sites.
Each site would be able to retrieve the user ID and salt from the cookie, then use the shared secret key (known only by the two applications) to calculate a SHA-2 signature that must match the SHA-2 signature stored in the cookie.
If the SHA-2 signatures match then you can assume that the user is authenticated, otherwise force the user to log in again.
The cookie must be destroyed when logging off.
The small print
To protect against session hijacking, all requests made over the two sites should be encrypted over SSL (use https.) If this is not possible, a hash based on the client's IP address as well as browser type and version (User-agent) should probably be calculated at login time and also be stored in the cookie. It should be re-checked against the client's IP address and user agent before serving each request. The hash-based approach is security through obscurity, and can be fooled; moreover, a user accessing the internet from behind a pool of proxies or using TOR may be kicked out by your system every time a different proxy or exit node (with a different IP address) forwards a request.

Related

Must be a top private domain

I'm learning about Google OAuth, and it says that my project has no appropriate credentials.
So I go to the Developers Console and click on the OAuth consent screen. I type my domain name into their question:
Authorized domains To protect you and your users, Google only allows
applications that authenticate using OAuth to use Authorized Domains.
Your applications' links must be hosted on Authorized Domains.
I have verified my domain, but I get "Must be a top private domain." The link takes me to some kind of java programming statement. Actually if I click on the Domain verification tab (again) there are no domain names listed, but I know I added it.
Q: How do I add my domain for being used with OAuth? Must I qualify it as a Top Private Domain or am I going down a rabbit hole?
Google oauth requires a top level domain for security purposes. A top level domain is the first one before the .com .net .biz, in other words it only has one dot. There are exceptions such as .co.uk.
Subdomains are controlled by the parent domains and are not necessarily owned or controlled by you. Imagine you have a Wordpress account at domain.wordpress.com. Wordpress closes your account and returns domain to inactive. A different user claims the domain user and domain.wordpress.com. If Google allowed subdomains they would be forced to believe the new user was you. (Since there is no requirement of public notification of the change)
Edit (a more generalized statement in response to a comment.)
If you own the domain, you have full control over it, and the ownership records are public. To prove your virtual identity as owner of the domain when subscribing to many services require a DNS record, that is created by you, as a challenge created by the provider, that can be read by the provider, prior to services being created. In the event of a change in ownership the original claimant, you, is sent a new record to the provided email address to add to your DNS server to prove you still own the domain. If you cannot prove you still maintain ownership of the name, as in the case of an expired domain hijack, all services are canceled.
Edit
The most probable problem is: Your domain verification is failing.
Start the verification process again. This will give you a new TXT record to add to your DNS.
Go to your DNS providers page and add the record. While there look for the refresh value on the SOA record.
Convert the SOA refresh from seconds to hours. Divide by 3600.
Wait that amount of time + 4 hours for replication.
Use nslookup (or dig) and look for the TXT record. Be sure to use Google's DNS server at 8.8.8.8(server=8.8.8.8).
If the record is not found, wait some more, if (hours waiting > 72) break; else repeat check.
If nslookup was able to find the record, complete the verification process; if not contact your DNS provider(The client record hold can be an issue).
If at this point everything went well, You should have an authorized domain.
If not (domain disappears, contact Google support), It my have to do with the privacy settings on the domain. Most quote public domains have contact information.
You must use a TLD (top level domain). If you have a subdomain, it is owned by the person who owns the TLD. For example, you might have a blog at myamazingblog.wordpress.com, and wanted to use OAuth with it. Unfortunately, this would not be possible, since you do not own wordpress.com (the TLD).
Try testing on a different device or clearing cache.
For me it turned out I had everything correct (just with my example.com domain) but my iOS safari was caching something and it kept giving me the ‘not whitelisted’ message. Which led me to think I needed to add dev.example.com as well - which isn’t necessary.
So try going to the site on another device or browser to see if it works.

How is a Cookie validated internally by ASP.NET MVC using CookieAuthenticationMiddleware

I'm trying to figure out how ASP.NET internally validates that a cookie will allow the user to access the application.
CookieAuthenticationMiddleware will set .AspNet.Cookies with an encrypted value. After .NET successfully decrypts the cookie on a request, what validation occurs then?
Developing locally with IISExpress if I have an application (#1) that sets an authentication Cookie after the user logs in, and I create a complete new application (#2) also running on localhost, that is also using CookieAuthentication. When I access #2 it will read the cookie from #1 and allows the user to access the application as well.
I'm trying to understand what the limits are for cookie authentication.
There's not really any "validation" per se. The cookie's encrypted key is used to reference the user that should be "logged in". It works in a very similar way to sessions, where the session cookie holds an encrypted session id that the server can use to look up and restore the session via.
The encryption/decryption is based on the machine key, which either may be explicitly set in the Web.config or generated automatically by ASP.NET. Only applications that share the same machine key may decrypt the cookie, which is why it's so important to protect your machine key.
Anyways, there's two factors involved here. First, cookies are domain bound: only the domain or subdomains of the domain the cookie is set on will be given the cookie. This is handled by the client (i.e. browser). Your two applications currently are able to both see the cookie because they're both running on localhost. However, if you were to deploy one at foo.com and the other at bar.com, then they would no longer be able to see each other's cookies.
Second, the machine key is typically by server (unless you explicitly set it in the Web.config per app). As a result, sites running on the same machine can usually decrypt each other's cookies (assuming they see them in the first place, which again, is based on their domain).
It's not clear whether you're happy or not about this arrangement. If your goal is to segregate the two sites running locally, such that they don't share cookies, you have a couple of options.
You can explicitly set a different machine key for each site in their respective Web.config files. They'll still receive any cookies set by the other site, but they'll no longer be able to decrypt them, which basically results in them being ignored.
You can customize the auth cookie name. Instead of using the default cookie name you can make one .Site1.Auth and the other .Site2.Auth. Then, even though either site will also receive the cookie for the other site, it will simply ignore it, because it's not the auth cookie for it.
If, however, you're intending to rely on this behavior in production as well (i.e. you actually want logging into one site to log you into the other as well), then you'll need to explicitly set the machine key to the same value in both site's Web.config files. Additionally, you'll need to deploy them on the same domain, or at least subdomains of that domain. In the case of subdomains, you'll need to set the cookie domain to be the wildcard domain .mydomain.com for both. Then, you could have one at foo.mydomain.com and another at bar.mydomain.com, and they'd both see the cookie because it was set on .mydomain.com. If you leave it the default, set on the actual domain of the site, then bar.mydomain.com could not see a cookie set by foo.mydomain.com because that cookie would be explicitly set only for foo.mydomain.com.
The primary validations are encryption and expiration. If apps share an encryption context (e.g. machine key) then they can share auth cookies (providing other client side sharing rules like domains and paths are satisfied). So yes it's expected that two apps using IIS Express localhost on the same machine would share cookies by default.
The expiration is also embedded in the encrypted value so the client can't tamper with it.

How do sessions and cookies work in Rails?

I have been using Devise for a while to handle authentication on my Rails apps, but never really understood how it works. Because Devise also uses the session storage config set on Rails, I'm assuming this is a question on session handling with Rails.
Basically, I'm an auth newbie. I've read a few articles about authentication but most deal with abstracted libraries (they talk about engines, middle ware, etc) that don't make much sense to me. I'm really looking for lower level details.
Here's what I know so far..
I know about cookies and sessions. Cookies are strings stored on client-side which is used to maintain session across multiple HTTP requests.
Here's my basic understanding of authentication (please correct me if I'm wrong):
When user logs in, we send the SSL encrypted request to the server. If the credentials are valid, we save a random string called session id on the database (or any other data store) as the valid session id associated with a user id. This session id changes for each login/logout of the user.
After saving that session id on our data store, we return a response that asks the browser to set a cookie with the session id. This session id along with the user id would then be sent for successive request to the domain until it expires. For each request, our server would check the session id on the headers and verify if that session id is valid for that user id. If it is, then consider that user authenticated.
Here are my questions:
I've read that by default starting from Rails 2, it now uses CookieStore (instead of SessionStore) which generates session hashes with SHA512 (instead of session ids), and all this is stored on a cookie which means multiple user id's can literally have the same session hash and it would just work fine. It seems to me that this is a very dangerous thing, exposing a large number of hashes with a single secret key stored on the server and basing your entire authentication system based on this key. Is there a real world large scale application that uses hashing instead of storing server side session id's?
On the topic of storing active session id's on server side, I've also read that you can switch to use different kinds of session storage for Rails. Based on this, I've heard of systems moving authentication systems out as services and using auth tokens instead. What's an auth token and how does it differ from a session id?
Seems like I can just keep guessing a random string (for both hashing and server side sessions) to grab an existing session. Is there a way to protect against this? Is it normal to use more values stored on a cookie? (such as the username, real name or even another hash for authentication)
I know I'm asking a lot but I believe this will be useful for people like me who do not understand authentication and will be very useful to get a solid foundation about the topic.
I've read that by default starting from Rails 2, it now uses
CookieStore (instead of SessionStore) which generates session hashes
with SHA512 (instead of session ids), and all this is stored on a
cookie which means multiple user id's can literally have the same
session hash and it would just work fine. It seems to me that this is
a very dangerous thing, exposing a large number of hashes with a
single secret key stored on the server and basing your entire
authentication system based on this key.
Yeah, it seems scary at first blush, but I'm not sure what the danger really is. In Rails 4, session data is encrypted using PBKBF2, and then signed with your session secret. This signing helps detect if the contents of the encrypted session have been tampered and the server will reject the session if it detects tampering.
https://cowbell-labs.com/2013-04-10-decrypt-rails-4-session.html
If someone gains access to the session token (which is used to sign the session cookie), you likely have much bigger problems on your hands than end-users attempting to impersonate the wrong user.
Is there a real world large scale application that uses hashing
instead of storing server side session id's?
I honestly don't know the answer to this one offhand, but I suspect that the fact that this is the "default" for Rails means that there are more than a handful of sites out there using cookie session stores.
On the topic of storing active session id's on server side, I've also
read that you can switch to use different kinds of session storage for
Rails. Based on this, I've heard of systems moving authentication
systems out as services and using auth tokens instead. What's an auth
token and how does it differ from a session id?
I'm doing this on a server now - basically a random hash is generated when a user authenticates, and that hash is stored, encrypted and signed, in the cookie. The cookie hash is a key into a server-side datastore (in my case Redis, but it can be in a relational database or memcache or whatever you like), and the actual session data is the stored server-side mapped to that key. This leaves less of your session data in the hands of the client were people could potentially decrypt and analyze it, so it's generally a bit safer.
Seems like I can just keep guessing a random string (for both hashing
and server side sessions) to grab an existing session. Is there a way
to protect against this? Is it normal to use more values stored on a
cookie? (such as the username, real name or even another hash for
authentication)
Yes, you could do that, but it would take a very very long time. You would also need to guess how to sign the newly tampered cookie data so that it'd match what the server expects to see on its side, and it's signed with a pretty large key.
I really don't think there's much alternative for persisting authentication state to using cookies (I suppose HTML5 Local Storage would work if you're feeling exotic and don't care much about legacy browser support).

How to fake Rails session that verifies session ID, IP address and http client

I'm rather new with Rails and I decided to bust my own authentication system that checks for 3 variable constants: IP address, Rails session ID and HTTP client. The way I am getting those are:
ip_address = request.env['action_dispatch.remote_ip'].to_s
session_id = request.env['action_dispatch.request.unsigned_session_cookie']['session_id'].to_s
http_client = request.env['HTTP_USER_AGENT'].to_s
Basically, since this is for personal use (for my blog) only, all I want is a single user access at a time.
My question is besides the 'HTTP_USER_AGENT', how can one fake those pieces of information from my web app? Is it possible to send a different IP address and session ID to Rails? Just theoretically. I'd like a glimpse of what's possible here...
Thanks.
Anything that the browser sends can be forged from another browser to impersonate what your own browser is sending.
The only exception here is the remote IP address. That one is extracted from the connection by the web server and cannot be easily forged.
So using your authentication mechanism you might as well forget the session ID and user agent. Both are vulnerable to replay attacks.
So basically your method of protection then becomes IP address protection. That's fine for some simple personal pages, but if you store sensitive information on those pages you might want to think about using something more secure.
You can read the Rails Security Guide to get a better understanding of which attacks are possible and some basic security principles with Rails.

OAuth and sticky sessions

I use OAuth 2 for authorization and need to implement it in a load balanced cluster. I've considered a few approaches, but it seems there is no way around a centralized approach. Here are my thoughts:
1. Balancing using source IP
Caching the tokens on one server and balancing by IP would be ideal, however, the IP can not assumed to be static. So when the same user tries to access services that require authorization from another IP with a valid token, it will fail, because it is not cached on this machine. Also other devices logged in with this user will not reach the same machine.
2. Balancing using a load balancing cookie
Also not really an option, since it cannot be assumed that every client implements cookie storage.
3. Balancing using the Authorization header
Balancing by hashing the Authorization: Bearer token header is problematic, because the first request (for requesting the authorization token) has no Authorization header, thus, the following request might not hit the same instance.
My current approach is to use a central Redis instance for authorization token storage.
Is there an option left, where a centralized approach can be avoided?
I think you still have two options to consider.
One is to balance by session ID. Application servers usually can be configured to manage sessions either by cookie or a GET parameter added to every link, so it does not definitely needs cookie storage. Additionally, there are very few HTTP clients left that still do not implement cookie storage, so you may want to reconsider item 2 of your list.
The other one is using self-contained tokens, e.g. JSON Web Tokens (JWT) with signatures (JWS). Validation of self-contained tokens may not need central database, each server instance can check token signatures alone and extract authorization details from the token itself. However, if you need support for revoking tokens, you may still need a central database to store at least a blacklist of revoked tokens.
Though I cannot provide you a full-fledged solution, hope this gives you some ideas.

Resources