class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_user!
end
const token = document.querySelector('meta[name="csrf-token"]').content;
await fetch('/settings/profile', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': token,
},
body: JSON.stringify({ display_name: 'Kai' }),
credentials: 'same-origin',
});
CSRF is still relevant whenever browsers automatically attach credentials. I keep standard anti-forgery tokens on server-rendered forms and use same-site cookies plus explicit bearer tokens for SPA APIs. The key is matching the defense to the authentication mechanism instead of assuming one pattern fits everything.