Here is some music to turn on while reading

When we’d like to have auth in mobile app we can do it in various ways nowdays. But what if we want to use rails to make it happen? Because thats just what we do :-D

Imagine if we can just use all the things rails offers somehow magically with minimal modification. All that good stuff somehow. There must be a way. Can we somehow just put user form in our mobile app and use rails sessions et al.

What if when rails issues a cookie we convert it to json and attach it to json response so that our app gets the cookie in easy way? That would work. We take cookie from json response and send it back. Sounds like it makes sense.

Lets intercept all requests that come out of rails and if its json request and cookie is being set lets take it from headers and put it in json body

  class RequestMiddlewhare
    def initialize(app)
      @app = app
    end
    def call(env)
      req = Rack::Request.new(env)

      status, headers, body = @app.call(env)
      if env["PATH_INFO"].match("json") && !env["REQUEST_METHOD"].match("OPTION")
        body[0] = JSON.parse(body[0]).merge({"Set-Cookie"=>headers["Set-Cookie"]}).to_json
      end
      [status, headers, body]
    end
  end
  config.middleware.insert_before 0, RequestMiddlewhare

Now how do we send it back? Usually in desktop how it works is that browser includes cookie automagically. We need to send it some other way. What if we include a paramter in each request we want checked. That sounds legitimate. Lets call that parameter cookie.

If we again intercept every request comming into rails and if we spot parameter cookie. We’ll make it so as if browser sent cookie. We will fill environment variable HTTP_COOKIE with content from request parameter. That should do the trick like so.

  class RequestMiddlewhare
    def initialize(app)
      @app = app
    end
    def call(env)
      req = Rack::Request.new(env)
      cookie = req.params[:cookie] || req.params["cookie"]
      if cookie
        cookie = Base64.decode64(cookie)
        #env["HTTP_COOKIE"] = Rack::Request.new(env).params[:cookie]
        env["HTTP_COOKIE"] = cookie
      end
      status, headers, body = @app.call(env)
      if env["PATH_INFO"].match("json") && !env["REQUEST_METHOD"].match("OPTION")
        body[0] = JSON.parse(body[0]).merge({"Set-Cookie"=>headers["Set-Cookie"]}).to_json
      end
      [status, headers, body]
    end
  end
  config.middleware.insert_before 0, RequestMiddlewhare

Now we have full power of rails sessions for a mobile app.

You have to put above code in

application.rb

like so

 module MyApp
   class Application < Rails::Application

    class RequestMiddlewhare
      def initialize(app)
        @app = app
      end
      def call(env)
        req = Rack::Request.new(env)
        cookie = req.params[:cookie] || req.params["cookie"]
        if cookie
          cookie = Base64.decode64(cookie)
          #env["HTTP_COOKIE"] = Rack::Request.new(env).params[:cookie]
          env["HTTP_COOKIE"] = cookie
        end
        status, headers, body = @app.call(env)
        if env["PATH_INFO"].match("json") && !env["REQUEST_METHOD"].match("OPTION")
          body[0] = JSON.parse(body[0]).merge({"Set-Cookie"=>headers["Set-Cookie"]}).to_json
        end
        [status, headers, body]
      end
    end
    config.middleware.insert_before 0, RequestMiddlewhare

  end
end

Cheers. You can copy freely if you need licence lets say it has MIT licence.

You might want to disable cors and put session tracking inside of cookie too like so So that you can call rails from mobile app.

module MyTestApp
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
      config.middleware.insert_before 0, Rack::Cors do

  allow do
    origins do |source, env|
      true
    end
     resource '*', :headers => :any, :methods => [:get, :post, :options], :credentials => true
   end
end


    class RequestMiddlewhare
      def initialize(app)
        @app = app
      end
      def call(env)
        req = Rack::Request.new(env)
        cookie = req.params[:cookie] || req.params["cookie"]
        if cookie
          cookie = Base64.decode64(cookie)
          #env["HTTP_COOKIE"] = Rack::Request.new(env).params[:cookie]
          env["HTTP_COOKIE"] = cookie
        end
        status, headers, body = @app.call(env)
        if env["PATH_INFO"].match("json") && !env["REQUEST_METHOD"].match("OPTION")
          body[0] = JSON.parse(body[0]).merge({"Set-Cookie"=>headers["Set-Cookie"]}).to_json
        end
        [status, headers, body]
      end
    end
    config.middleware.insert_before 0, RequestMiddlewhare

    config.load_defaults 6.0

    config.allow_forgery_protection=false
    config.session_store :cookie_store, key: '_interslice_session'
    config.middleware.use ActionDispatch::Cookies # Required for all session management
    config.middleware.use ActionDispatch::Session::CookieStore, config.session_options
    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.
  end
end