Git Product home page Git Product logo

plug_rails_cookie_session_store's Introduction

PlugRailsCookieSessionStore

Rails compatible Plug session store.

This allows you to share session information between Rails and a Plug-based framework like Phoenix.

Version Information

Version 2.0 and higher require OTP 22 or higher.

Installation

Add PlugRailsCookieSessionStore as a dependency to your mix.exs file:

def deps do
  [{:plug_rails_cookie_session_store, "~> 2.0"}]
end

How to use with Phoenix

Copy/share the encryption information from Rails to Phoenix.

There are 4 things to copy:

  • secret_key_base
  • signing_salt
  • encryption_salt
  • session_key

Since Rails 5.2, secret_key_base in test and development is derived as a MD5 hash of the application's name. To fetch key value you can run:

Rails.application.secret_key_base

https://www.rubydoc.info/github/rails/rails/Rails%2FApplication:secret_key_base

The secret_key_base should be copied to Phoenix's config.exs file. There should already be a key named like that and you should override it.

The other three values can be found somewhere in the initializers directory of your Rails project. Some people don't set the signing_salt and encryption_salt. If you don't find them, set them like so:

Rails.application.config.session_store :cookie_store, key: '_SOMETHING_HERE_session'
Rails.application.config.action_dispatch.encrypted_cookie_salt =  'encryption salt'
Rails.application.config.action_dispatch.encrypted_signed_cookie_salt = 'signing salt'

Configure the Cookie Store in Phoenix.

Edit the endpoint.ex file and add the following:

# ...
plug Plug.Session,
  store: PlugRailsCookieSessionStore,
  key: "_SOMETHING_HERE_session",
  domain: '.myapp.com',
  secure: true,
  signing_with_salt: true,
  signing_salt: "signing salt",
  encrypt: true,
  encryption_salt: "encryption salt",
  key_iterations: 1000,
  key_length: 64,
  key_digest: :sha,
  serializer: Poison # see serializer details below
end

Set up a serializer

Plug & Rails must use the same strategy for serializing cookie data.

  • JSON: Since 4.1, Rails defaults to serializing cookie data with JSON. Support this strategy by getting a JSON serializer and passing it to Plug.Session. For example, add Poison to your dependencies, then:

    plug Plug.Session,
      store: PlugRailsCookieSessionStore,
      # ... see encryption config above
      serializer: Poison
    end

    You can confirm that your app uses JSON by searching for

    Rails.application.config.action_dispatch.cookies_serializer = :json

    in an initializer.

  • Marshal: Previous to 4.1, Rails defaulted to Ruby's Marshal library for serializing cookie data. You can deserialize this by adding ExMarshal to your project and defining a serializer module:

    defmodule RailsMarshalSessionSerializer do
      @moduledoc """
      Share a session with a Rails app using Ruby's Marshal format.
      """
      def encode(value) do
        {:ok, ExMarshal.encode(value)}
      end
    
      def decode(value) do
        {:ok, ExMarshal.decode(value)}
      end
    end

    Then, pass that module as a serializer to Plug.Session:

    plug Plug.Session,
      store: PlugRailsCookieSessionStore,
      # ... see encryption config above
      serializer: RailsMarshalSessionSerializer
    end
  • Rails 3.2: Rails 3.2 uses unsalted signing, to make Phoenix share session with Rails 3.2 project you need to set up ExMarshal mentioned above, with following configuration in your Plug.Session:

    plug Plug.Session,
      store: PlugRailsCookieSessionStore,
      # ... see encryption/ExMarshal config above
      signing_with_salt: false,
    end

That's it!

To test it, set a session value in your Rails application:

session[:foo] = 'bar'

And print it on Phoenix in whatever Controller you want:

Logger.debug get_session(conn, "foo")

plug_rails_cookie_session_store's People

Contributors

andrewtimberlake avatar caspg avatar cconstantin avatar edmz avatar gaynetdinov avatar hisea avatar joerichsen avatar msramos avatar rmosolgo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

plug_rails_cookie_session_store's Issues

Having trouble sharing session between rails 3 and phoenix

I followed the read me to setup ExMarshal but couldnt get it working.

I understand that Rails 3.2.22 is signed but not encrypted, I set up my phoenix endpoint according to README but doesn't seem to work.

If any one got this working can you please share some insight on configuration?

Thanks

In Rails 7.1 the cookie format has changed compared to 7.0. Breaks Phx->Rails, but not Rails->Phx transition.

Problem

In Rails 7.1 (which bumps Rack from 2.2.8 to 3.0.9.1 and rack-session to 2.0.0) the cookies are not compatible with Rails 7.0. When I copy in Chrome from Tools - Application tab - Storage section - Cookies the encrypted content of a cookie created in Rails 7.1, make a git checkout to the previous commit where I am on Rails 7.0 and paste the cookie - it is not recognized. But if I do the same between Rails 7.0 and Rails 6.0 it is recognized. Same happens between Rails 7.1 and Phoenix using plug_rails_cookie_session_store, except that the cookies are normally read and used when transitioning from Rails 7.1. to Phoenix, but then when I click on a link back to the Rails 7.1 app - the cookies are not recognized - so it is only the put(conn, _sid, term, opts) that does not work properly, while the get() and init() are fine.

Moreover Rails 7.1 puts the "unrecognized" cookies into the encrypted "message" (cookies[_rails][message][_rails][message]... etc.), so when the user clicks multiple times to switch from Phx to Rails back and forth - the message becomes longer and longer and soon Rails raises ActionDispatch::Cookies::CookieOverflow.

Attempts to solve

I tried 7.1 with older versons of Rack/Rack-sesson, but it did not work.

The :sha -> :sha256 change is done for both 7.0 and 7.1. :sha is only for 6.0 and 6.1. Anyway, since the get() func works, the encryption should not be the problem, but some kind of formatting I guess.

Current bad solution

Revert back to Rails 7.0

Related issue

Probably related to this issue - rails/rails#48195 . But I could not find the "[" prefix as described or any other solution for Rails 7.1.

Cannot write session

Using (at least) Phoenix 1.3, I cannot get the way to write into the session effectively.

At the moment I'm able to read the Rails session correctly, but nothing I write on the session is finally written in the cookie.

I've just put a test plug to print in console the content opf the session, and everything written in Rails appears, but not the things written in Phoenix. As expected, that avoids also the correct work of CSRF protection (as the key is stored in session).

Any ideas want can be happening?

My config:

  plug Plug.Session,
    store: PlugRailsCookieSessionStore,
    key: "_myapp_session",
    domain: '.acutario.dev',
    secure: true,
    signing_with_salt: true,
    signing_salt: "signing salt",
    encrypt: true,
    encryption_salt: "encryption salt",
    key_iterations: 1000,
    key_length: 64,
    key_digest: :sha,
    serializer: Poison

Thanks!

nil can't be coerced into Fixnum

When I share a session created in Phoenix with my Rails 4.2 app I get the following exception in my views when calling form_authenticity_token or csrf_meta_tags. Any ideas?

nil can't be coerced into Fixnum

comes from this line:

vendor/bundle/ruby/2.3.0/gems/actionpack-4.2.8/lib/action_controller/metal/request_forgery_protection.rb:321

def xor_byte_strings(s1, s2)
  s1.bytes.zip(s2.bytes).map { |(c1,c2)| c1 ^ c2 }.pack('c*')
end

mix test fail

Hi, mix test fail,

I run

mix deps.update
mix test

......

  1. test gets and sets custom serialized session cookie (PlugRailsCookieSessionStoreTest)
    test/plug_rails_cookie_session_store_test.exs:175
    Assertion with == failed
    code: conn(:get, "/") |> recycle_cookies(conn) |> custom_serialize_conn() |> get_session(:foo) == "bar"
    lhs: nil
    rhs: "bar"
    stacktrace:
    test/plug_rails_cookie_session_store_test.exs:180: (test)

................

Finished in 0.2 seconds
23 tests, 1 failure

LiveView Configuration Issue - LiveView session was misconfigured or the user token is outdated

Has anyone been able to get this working with LiveView or have any recommendations as to how I might debug this issue...

I am starting with https://github.com/dersnek/chirp as a working application

I get the following errors after setting everything up per the instructions... it seems like everything is as it should be

[debug] LiveView session was misconfigured or the user token is outdated.

1) Ensure your session configuration in your endpoint is in a module attribute:

    @session_options [
      ...
    ]

2) Change the `plug Plug.Session` to use said attribute:

    plug Plug.Session, @session_options

3) Also pass the `@session_options` to your LiveView socket:

    socket "/live", Phoenix.LiveView.Socket,
      websocket: [connect_info: [session: @session_options]]

4) Define the CSRF meta tag inside the `<head>` tag in your layout:

    <%= csrf_meta_tag() %>

5) Pass it forward in your app.js:

    let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content");
    let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}});

[info] REFUSED CONNECTION TO Phoenix.LiveView.Socket in 452µs
  Transport: :websocket
  Serializer: Phoenix.Socket.V2.JSONSerializer
  Parameters: %{"_csrf_token" => "Kzo_DhAfHjhVMH19RkUJfxEHICQcIQdqfNqFJyuA9ADH26DLUuWfnbQG", "vsn" => "2.0.0"}

My endpoint.ex file has the following sections:

  @session_options [
    store: PlugRailsCookieSessionStore,
    key: "_chirp_key",
    secure: true,
    signing_with_salt: true,
    signing_salt: "signed cookie",
    encrypt: true,
    encryption_salt: "signed encrypted cookie",
    key_iterations: 1000,
    key_length: 64,
    key_digest: :sha,
    serializer: Poison,
  ]
  ]
  socket "/socket", ChirpWeb.UserSocket,
    websocket: true,
    longpoll: false

  socket "/live", Phoenix.LiveView.Socket, websocket: [ connect_info: [session: @session_options]]
  plug Plug.MethodOverride
  plug Plug.Head
  plug Plug.Session, @session_options
  plug ChirpWeb.Router

Issues with Rails 5.2.2

In a brand new Rails 5.2.2 app attempting to communicate with a Phoenix 1.4.0 (Cowboy 2.7.0) app I was unable to get this plug to work. After double and triple checking I had the correct environment variables I started to try and figure out where the problem might be.

In message_verifier.ex the verify function looks like it attempts to split a cookie value of something like abcdefgh--abcdef(2 segments). However mine had 3 segments, eg. abcdefgh--abcdef--abcdef.

I downgraded to Rails 5.0.0 and everything immediately started working so I'm guessing it must be a problem with the latest Rails version.

Has anyone else experienced the same issue?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.