Mark Richman
Mark Richman

Reputation: 29720

Rails and ASP.NET Single Sign-On

I have an ASP.NET app which uses forms auth, and stores the credentials in a table - pretty vanilla. Since I know how the password is hashed, can I somehow share the forms auth cookie with Rails, effectively creating a single sign-on? Both web apps will live in the same domain.

Upvotes: 4

Views: 917

Answers (2)

Fábio Batista
Fábio Batista

Reputation: 25280

You can share the ASP.NET Forms Auth Cookie with Rails, but you'll have to decrypt it on the Rails side. Maybe it's too much trouble.

A simpler solution is to skip .NET Forms Authentication Ticket and persist your own auth ticket (cookie) on both sides, using the encryption algorithm you want and the same salt among the two platforms. The salt can be saved on the database or a physical file, if they reside on the same disk.

An example:

C# side:

public class MyTicket {
  ...
  public string ToSerializableFormat() {
    return String.Format("{0}|{1}", t.Username, t.somethingElseYouNeed);
  }

  public static MyTicket Parse(string value) {
    var vals = value.Split('|');
    return MyTicket(values[0], values[1]);
  }
}

Somewhere else in your application, replacing the FormsAuthentication.Encrypt and FormsAuthentication.Decrypt calls:

string MakeTicket(MyTicket t) {
  return EncryptSomehow(key, t.ToSerializableFormat());
}

MyTicket ReadTicket(string cookieValue) {
  return MyTicket.Parse( DecryptSomehow(key, cookieValue) );
}

And the Ruby-equivalent would be:

class MyTicket
  def to_serializable_format
    "#{@username}|#{@something_else}"
  end

  def self.parse(value)
    values = value.split '|'
    MyTicket.new(*values)
  end
end

Somewhere in your Rails code you'll decrypt and encrypt the auth cookie. Use the same name on both sides.

Profit.

Upvotes: 7

Adam Lassek
Adam Lassek

Reputation: 35515

I don't know about sharing the auth cookie -- that would probably be difficult. But sharing the identity information would be pretty simple.

I would write a user model in Rails that acts as an adapter to your existing identity table, using the establish_connection trick:

class User < ActiveRecord::Base
  establish_connection(
    { :adapter => "mysql", 
      :database => "db_name", 
      :host => "db.example.com",
      :username => "user",
      :password => "password" })
end

this will make the User model connect to a different db. Event better, you could add another entry in database.yml and load it here.

Then, you would simply need to overload the accessor functions to deal with the non-standard schema.

Upvotes: 0

Related Questions