使用devise_token_auth构建带Facebook登录的Rails API时遇属性错误
Hey there, that ActiveModel::ForbiddenAttributesError is a classic Rails strong parameters issue—Rails is blocking unpermitted attributes from being assigned to your User model when the Facebook OAuth callback completes. DeviseTokenAuth's default OmniAuth handling might not be whitelisting all the attributes coming back from Facebook, so we need to explicitly allow them. Here's how to fix it step by step:
1. Create a Custom Omniauth Callbacks Controller
First, we'll override DeviseTokenAuth's default callbacks controller to handle parameter whitelisting and attribute assignment properly.
Generate a new controller (or create it manually):
rails generate controller OmniauthCallbacks
Replace the contents of app/controllers/omniauth_callbacks_controller.rb with this:
class OmniauthCallbacksController < DeviseTokenAuth::OmniauthCallbacksController protected # Whitelist the parameters coming from Facebook OAuth def omniauth_params params.permit(:provider, :uid, :name, :email, :token, :expires_in, :auth_origin_url, :client_id) end # Assign attributes from Facebook's auth hash to your User model def assign_provider_attrs(user, auth_hash) # Only set these if the user doesn't already have them (prevents overwriting existing data) user.name = auth_hash['info']['name'] unless user.name.present? user.email = auth_hash['info']['email'] unless user.email.present? # Add any other attributes you want to pull from Facebook, like avatar URL: # user.avatar_url = auth_hash['info']['image'] unless user.avatar_url.present? user end end
2. Update Your Routes to Use the Custom Controller
Modify config/routes.rb to point DeviseTokenAuth's Omniauth callbacks to your new controller. Replace your existing mount_devise_token_auth_for line with:
mount_devise_token_auth_for 'User', at: 'auth', controllers: { omniauth_callbacks: 'omniauth_callbacks' }
3. (Optional) Update Your User Model's Permitted Attributes
To be extra safe, explicitly define the attributes your User model accepts in app/models/user.rb:
class User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable include DeviseTokenAuth::Concerns::User def self.devise_token_auth_permitted_attributes # Add any additional attributes you need here super + [:name, :email, :provider, :uid] end end
4. Verify Your DeviseTokenAuth Configuration
Double-check your config/initializers/devise_token_auth.rb to ensure Facebook is properly configured with your app credentials and callback URL:
DeviseTokenAuth.setup do |config| config.omniauth :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'], callback_url: ENV['FACEBOOK_CALLBACK_URL'], # Should be http://localhost:3000/auth/facebook/callback in dev scope: 'email,public_profile' # Make sure you're requesting the right permissions end
Why This Works
The ForbiddenAttributesError happens because Rails blocks any attributes that aren't explicitly permitted via strong parameters. By overriding omniauth_params, we tell Rails which parameters from the Facebook OAuth response are safe to use. The assign_provider_attrs method ensures we correctly map Facebook's returned data to your User model's attributes without triggering the error.
After making these changes, restart your Rails server and try the Facebook login flow again—it should now complete without the forbidden attributes error.
内容的提问来源于stack exchange,提问作者Daniel

