sahat / satellizer

Token-based AngularJS Authentication
https://satellizer-sahat.rhcloud.com
MIT License
7.85k stars 1.13k forks source link

Rails + Angular CORS #351

Open brzezinskip opened 9 years ago

brzezinskip commented 9 years ago

Hello. I've been trying to implement Satellizer (which is an awesome tool by the way) into my angular app and it was (almost) sucessful, but I have a weird problem with CORS which I can't figure out. When I run my in chrome with --disable-web-secrutiy I can register/authenticate without any problems, but when I try to run it without that option things get messy.

So what I do is- click on button which runs $auth.authenticate in my controller, facebook/google (I only use these two) popup appears, I fill in my data, accept everything, popup disappears and in console I get an error which says "XMLHttpRequest cannot load http://127.0.0.1:3000/auth/google_oauth2. The request was redirected to 'https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=142…scope=email+profile&state=1651b2916b69913f87b6dfb325a6eda72954fed6619e99d3', which is disallowed for cross-origin requests that require preflight."

I will try to post as many informations as I can, because I've spent many hours trying to fix it myself, but it looks like I am missing something. So, my frontend config file looks like that:

.config ($httpProvider, $authProvider,  jwtInterceptorProvider, RestangularProvider, ENV) ->
  RestangularProvider.setBaseUrl(ENV.API_URL)
  RestangularProvider.setRequestSuffix('.json')
  $httpProvider.defaults.useXDomain = true;

  delete $httpProvider.defaults.headers.common['X-Requested-With'];

  $httpProvider.defaults.headers.patch['Content-Type'] = 'application/json'
  $httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content')

  jwtInterceptorProvider.tokenGetter = (store) ->
    return store.get('jwt')

  $httpProvider.interceptors.push('jwtInterceptor')

  $authProvider.google
    clientId: "myclientid"
    url: "http://127.0.0.1:3000/auth/google_oauth2"
    redirectUri: "http://127.0.0.1:4400"

google configuration: zrzut ekranu 2015-04-13 23 46 37

And I run this using ng-click pointing to controller's action, which looks like that:

  $scope.authenticate = (provider) ->
    $auth.authenticate(provider).then (response) ->
      store.set('jwt', response.data.token)
      store.set('currentUserId', response.data.user_id)
      if AuthServ.isAuthenticated()
        $state.go ('root.main')

Ruby on Rails part: In routes I've got

match '/auth/:provider/callback', to: 'api/v1/oauth#create', via: 'get'

which points to my create action looking like that:

module Api
  module V1
    class OauthController < ApplicationController
      require 'auth_token'

      def create
        binding.pry
        auth_hash = request.env['omniauth.auth']
        auth = Authorization.find_or_create(auth_hash)
        @token = AuthToken.issue_token(user_id: auth.user.id)
        render json: { token: @token, user_id: auth.user.id }, status: 200
      end
    end
  end
end

And going further, my Authorization model looks like this:

class Authorization < ActiveRecord::Base
  validates :provider, presence: true
  validates :uid, presence: true

  belongs_to :user

  def self.find_or_create(auth_hash)
    auth = find_by_provider_and_uid(auth_hash['provider'], auth_hash['uid'])
    unless auth
      user = User.create(first_name: auth_hash['info']['name'], password: Digest::SHA2.hexdigest(Time.now.to_s), email: auth_hash['info']['email'])
      auth = create(user: user, provider: auth_hash['provider'], uid: auth_hash['uid'])
    end
    auth
  end
end

I have tried adding CORS in rails using rack::cors, but it didn't change anything, this is how it looks like:

module MyappBackend
  class Application < Rails::Application
    config.active_record.raise_in_transactional_callbacks = true

    # Allow cross-domain requests
    config.middleware.insert_before 0, "Rack::Cors", :debug => true, :logger => (-> { Rails.logger }) do
      allow do
        origins '*'
        resource '*', headers: :any, methods: [:get, :post, :put, :patch, :delete, :options],
        max_age: 0
      end
    end
  end
end

I've tried to apply anything I could find in google, but without any luck. The thing is- with --disable-web-security everything works smooth, but when I try to run chrome/safari/firefox in normal mode, I always get that darn CORS error.

I have tried to debug satellizer.js and found out that in line 487:

return $http.post(defaults.url, data, { withCredentials: config.withCredentials });

I always get to an error, with data, status and header looking like this: zrzut ekranu 2015-04-13 23 57 28

Any ideas how to get it working? I am out of ideas. Please provide me any informations that might be useful and keep it up with your awesome project. Regards.

logicalgroove commented 8 years ago

@luseerr did you ever got this working?