<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Ruby on Rails on IAMDevBox</title><link>https://www.iamdevbox.com/tags/ruby-on-rails/</link><description>Recent content in Ruby on Rails on IAMDevBox</description><image><title>IAMDevBox</title><url>https://www.iamdevbox.com/IAMDevBox.com.jpg</url><link>https://www.iamdevbox.com/IAMDevBox.com.jpg</link></image><generator>Hugo -- 0.146.0</generator><language>en-us</language><lastBuildDate>Sat, 11 Apr 2026 14:37:04 +0000</lastBuildDate><atom:link href="https://www.iamdevbox.com/tags/ruby-on-rails/index.xml" rel="self" type="application/rss+xml"/><item><title>Secure Ruby on Rails RAG Applications with Auth0 FGA</title><link>https://www.iamdevbox.com/posts/secure-ruby-on-rails-rag-applications-with-auth0-fga/</link><pubDate>Sat, 11 Apr 2026 14:37:01 +0000</pubDate><guid>https://www.iamdevbox.com/posts/secure-ruby-on-rails-rag-applications-with-auth0-fga/</guid><description>Learn how to secure Ruby on Rails RAG applications using Auth0 FGA to prevent data leakage and ensure that only authorized users access specific documents.</description><content:encoded><![CDATA[<h2 id="why-this-matters-now">Why This Matters Now</h2>
<p>With the rise of AI-driven applications, especially those leveraging Retrieval-Augmented Generation (RAG), securing sensitive data has become paramount. Recent incidents highlight the risks associated with improper handling of vectors and embeddings. Ensuring that only authorized users can access specific documents is critical to maintaining data integrity and privacy. This becomes urgent as more companies integrate RAG into their systems, making it essential to implement robust security measures.</p>
<h2 id="understanding-the-rag-application">Understanding the RAG Application</h2>
<p>Let&rsquo;s start by examining a Ruby on Rails RAG application called Work Companion. This app acts as a chat interface for employees, providing answers based on internal company documents. The challenge here is to ensure that users can only access documents they are permitted to see, preventing any accidental exposure of sensitive information.</p>
<h3 id="the-rag-process">The RAG Process</h3>
<ol>
<li><strong>Retrieval</strong>: When a user asks a question, the app searches a vector database to find the most relevant text chunks from the available documents.</li>
<li><strong>Augmentation</strong>: These text chunks are added to the user&rsquo;s original question to provide more context.</li>
<li><strong>Generation</strong>: The combined input is sent to a Language Model (LLM) to generate a precise response.</li>
</ol>
<h3 id="example-scenario">Example Scenario</h3>
<p>Imagine an Engineer asking about &ldquo;salary bands.&rdquo; In a poorly secured RAG setup, the vector search might inadvertently retrieve a snippet from a private HR document. By integrating Auth0 FGA, we ensure that only documents the user is authorized to access are considered during the retrieval process.</p>
<h2 id="setting-up-the-work-companion-app">Setting Up the Work Companion App</h2>
<h3 id="prerequisites">Prerequisites</h3>
<ul>
<li>Ruby 4.0.1</li>
<li>PostgreSQL 17 with pgvector extension</li>
<li>An OpenAI API key</li>
</ul>
<h3 id="database-schema">Database Schema</h3>
<p>The app uses a simple schema with three tables:</p>
<ul>
<li><strong>users</strong>: Stores user information.</li>
<li><strong>documents</strong>: Contains metadata about each document.</li>
<li><strong>document_chunks</strong>: Holds the vector embeddings and uses an HNSW index for efficient searching.</li>
</ul>
<h3 id="services">Services</h3>
<ul>
<li><strong>RagQueryService</strong>: Manages the RAG flow.</li>
<li><strong>FgaService</strong>: Interfaces with the Auth0 FGA API to fetch user permissions.</li>
</ul>
<h3 id="gems">Gems</h3>
<ul>
<li><strong>neighbor</strong>: Handles pgvector within ActiveRecord.</li>
<li><strong>ruby-openai</strong>: Connects to OpenAI for generating embeddings.</li>
<li><strong>openfga</strong>: Ruby SDK for interacting with Auth0 FGA.</li>
</ul>
<h2 id="running-the-code-sample">Running the Code Sample</h2>
<p>First, clone and install the dependencies:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git clone https://github.com/auth0-blog/ruby-rag-fga
</span></span><span style="display:flex;"><span>cd ruby-rag-fga
</span></span><span style="display:flex;"><span>bundle install
</span></span></code></pre></div><p>Next, set up PostgreSQL with the pgvector extension, create the database, and seed it with data. Follow the steps in the repo&rsquo;s README. Start the server with:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>rails s
</span></span></code></pre></div><p>Navigate to <code>http://localhost:3000</code> to see the chat interface.</p>
<h2 id="adding-authentication-with-auth0">Adding Authentication with Auth0</h2>
<p>Before integrating Auth0 FGA, we need to authenticate users. Auth0 handles identity management, ensuring we know exactly who the user is.</p>
<h3 id="step-by-step-guide">Step-by-Step Guide</h3>
<ol>
<li>
<p><strong>Create an Auth0 Application</strong>:</p>
<ul>
<li>Go to the Auth0 dashboard and create a new &ldquo;Regular Web Application.&rdquo;</li>
<li>Note down the Domain, Client ID, and Client Secret.</li>
</ul>
</li>
<li>
<p><strong>Install and Set Up the Auth0 SDK</strong>:</p>
<ul>
<li>
<p>Add the following to your Gemfile:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>source <span style="color:#e6db74">&#34;https://rubygems.org&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ...</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Auth0 Authentication</span>
</span></span><span style="display:flex;"><span>gem <span style="color:#e6db74">&#34;omniauth-auth0&#34;</span>, <span style="color:#e6db74">&#34;~&gt; 3.1&#34;</span>
</span></span><span style="display:flex;"><span>gem <span style="color:#e6db74">&#34;omniauth-rails_csrf_protection&#34;</span>, <span style="color:#e6db74">&#34;~&gt; 1.0&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ...</span>
</span></span></code></pre></div></li>
<li>
<p>Install the gems:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>bundle install
</span></span></code></pre></div></li>
</ul>
</li>
<li>
<p><strong>Configure Auth0 in Rails</strong>:</p>
<ul>
<li>
<p>Create a new initializer file <code>config/initializers/auth0.rb</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">OmniAuth</span><span style="color:#f92672">.</span>config<span style="color:#f92672">.</span>logger <span style="color:#f92672">=</span> <span style="color:#66d9ef">Rails</span><span style="color:#f92672">.</span>logger
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">Rails</span><span style="color:#f92672">.</span>application<span style="color:#f92672">.</span>config<span style="color:#f92672">.</span>middleware<span style="color:#f92672">.</span>use <span style="color:#66d9ef">OmniAuth</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Builder</span> <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>  provider(
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">:auth0</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">ENV</span><span style="color:#f92672">[</span><span style="color:#e6db74">&#39;AUTH0_CLIENT_ID&#39;</span><span style="color:#f92672">]</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">ENV</span><span style="color:#f92672">[</span><span style="color:#e6db74">&#39;AUTH0_CLIENT_SECRET&#39;</span><span style="color:#f92672">]</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">ENV</span><span style="color:#f92672">[</span><span style="color:#e6db74">&#39;AUTH0_DOMAIN&#39;</span><span style="color:#f92672">]</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">callback_path</span>: <span style="color:#e6db74">&#39;/auth/auth0/callback&#39;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">failure_path</span>: <span style="color:#e6db74">&#39;/auth/failure&#39;</span>
</span></span><span style="display:flex;"><span>  )
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">OmniAuth</span><span style="color:#f92672">.</span>config<span style="color:#f92672">.</span>on_failure <span style="color:#f92672">=</span> <span style="color:#66d9ef">Proc</span><span style="color:#f92672">.</span>new <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>env<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">OmniAuth</span><span style="color:#f92672">::</span><span style="color:#66d9ef">FailureEndpoint</span><span style="color:#f92672">.</span>new(env)<span style="color:#f92672">.</span>redirect_to_failure
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div></li>
</ul>
</li>
<li>
<p><strong>Set Environment Variables</strong>:</p>
<ul>
<li>
<p>Add your Auth0 credentials to your <code>.env</code> file:</p>



<div class="goat svg-container ">
  
    <svg
      xmlns="http://www.w3.org/2000/svg"
      font-family="Menlo,Lucida Console,monospace"
      
        viewBox="0 0 312 57"
      >
      <g transform='translate(8,16)'>
<text text-anchor='middle' x='0' y='4' fill='currentColor' style='font-size:1em'>A</text>
<text text-anchor='middle' x='0' y='20' fill='currentColor' style='font-size:1em'>A</text>
<text text-anchor='middle' x='0' y='36' fill='currentColor' style='font-size:1em'>A</text>
<text text-anchor='middle' x='8' y='4' fill='currentColor' style='font-size:1em'>U</text>
<text text-anchor='middle' x='8' y='20' fill='currentColor' style='font-size:1em'>U</text>
<text text-anchor='middle' x='8' y='36' fill='currentColor' style='font-size:1em'>U</text>
<text text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'>T</text>
<text text-anchor='middle' x='16' y='20' fill='currentColor' style='font-size:1em'>T</text>
<text text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'>T</text>
<text text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'>H</text>
<text text-anchor='middle' x='24' y='20' fill='currentColor' style='font-size:1em'>H</text>
<text text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'>H</text>
<text text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'>0</text>
<text text-anchor='middle' x='32' y='20' fill='currentColor' style='font-size:1em'>0</text>
<text text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'>0</text>
<text text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='40' y='20' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'>C</text>
<text text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'>C</text>
<text text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'>D</text>
<text text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'>L</text>
<text text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'>L</text>
<text text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'>O</text>
<text text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'>I</text>
<text text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'>I</text>
<text text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'>M</text>
<text text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'>E</text>
<text text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'>E</text>
<text text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'>A</text>
<text text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'>N</text>
<text text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'>N</text>
<text text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'>I</text>
<text text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'>T</text>
<text text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'>T</text>
<text text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'>N</text>
<text text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'>=</text>
<text text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'>I</text>
<text text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'>S</text>
<text text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'>y</text>
<text text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'>D</text>
<text text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'>E</text>
<text text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'>=</text>
<text text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'>C</text>
<text text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'>y</text>
<text text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'>R</text>
<text text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'>E</text>
<text text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'>T</text>
<text text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'>d</text>
<text text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'>=</text>
<text text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'>y</text>
<text text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='200' y='20' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='208' y='20' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='216' y='20' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='224' y='20' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'>h</text>
<text text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'>d</text>
<text text-anchor='middle' x='232' y='20' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'>0</text>
<text text-anchor='middle' x='240' y='20' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='256' y='20' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='264' y='20' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='272' y='20' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='280' y='20' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='288' y='20' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='296' y='20' fill='currentColor' style='font-size:1em'>t</text>
</g>

    </svg>
  
</div>
</li>
</ul>
</li>
<li>
<p><strong>Create Routes for Authentication</strong>:</p>
<ul>
<li>
<p>Add the following routes to <code>config/routes.rb</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>get <span style="color:#e6db74">&#39;/auth/auth0/callback&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;auth0#callback&#39;</span>
</span></span><span style="display:flex;"><span>get <span style="color:#e6db74">&#39;/auth/failure&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;auth0#failure&#39;</span>
</span></span><span style="display:flex;"><span>get <span style="color:#e6db74">&#39;/logout&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;auth0#logout&#39;</span>
</span></span></code></pre></div></li>
</ul>
</li>
<li>
<p><strong>Implement Auth0 Controller</strong>:</p>
<ul>
<li>
<p>Create a controller <code>app/controllers/auth0_controller.rb</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Auth0Controller</span> <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">ApplicationController</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">callback</span>
</span></span><span style="display:flex;"><span>    session<span style="color:#f92672">[</span><span style="color:#e6db74">:userinfo</span><span style="color:#f92672">]</span> <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span>env<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;omniauth.auth&#39;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    redirect_to root_path
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">failure</span>
</span></span><span style="display:flex;"><span>    @error_type <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span>params<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;error_type&#39;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    @error_msg <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span>params<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;error_description&#39;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    flash<span style="color:#f92672">[</span><span style="color:#e6db74">:alert</span><span style="color:#f92672">]</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Authentication error: </span><span style="color:#e6db74">#{</span>@error_msg<span style="color:#e6db74">}</span><span style="color:#e6db74">.&#34;</span>
</span></span><span style="display:flex;"><span>    redirect_to root_path
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">logout</span>
</span></span><span style="display:flex;"><span>    reset_session
</span></span><span style="display:flex;"><span>    redirect_to logout_url<span style="color:#f92672">.</span>to_s
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">private</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">logout_url</span>
</span></span><span style="display:flex;"><span>    domain <span style="color:#f92672">=</span> <span style="color:#66d9ef">ENV</span><span style="color:#f92672">[</span><span style="color:#e6db74">&#39;AUTH0_DOMAIN&#39;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    client_id <span style="color:#f92672">=</span> <span style="color:#66d9ef">ENV</span><span style="color:#f92672">[</span><span style="color:#e6db74">&#39;AUTH0_CLIENT_ID&#39;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    params <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">returnTo</span>: root_url,
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">client_id</span>: client_id
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">URI</span><span style="color:#f92672">::</span><span style="color:#66d9ef">HTTPS</span><span style="color:#f92672">.</span>build(<span style="color:#e6db74">host</span>: domain, <span style="color:#e6db74">path</span>: <span style="color:#e6db74">&#39;/v2/logout&#39;</span>, <span style="color:#e6db74">query</span>: params<span style="color:#f92672">.</span>to_query)
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div></li>
</ul>
</li>
<li>
<p><strong>Update Views</strong>:</p>
<ul>
<li>
<p>Add login and logout links in your views. For example, in <code>app/views/layouts/application.html.erb</code>:</p>
<pre tabindex="0"><code class="language-erb" data-lang="erb">&lt;% if session[:userinfo] %&gt;
  &lt;p&gt;Welcome &lt;%= session[:userinfo][:info][:name] %&gt;!&lt;/p&gt;
  &lt;%= link_to &#39;Logout&#39;, logout_path %&gt;
&lt;% else %&gt;
  &lt;%= link_to &#39;Login&#39;, &#39;/auth/auth0&#39; %&gt;
&lt;% end %&gt;
</code></pre></li>
</ul>
</li>
</ol>
<h2 id="integrating-auth0-fga-for-fine-grained-authorization">Integrating Auth0 FGA for Fine-Grained Authorization</h2>
<p>Now that users are authenticated, we need to ensure they can only access documents they are authorized to see. Auth0 FGA provides the necessary tools to implement fine-grained authorization.</p>
<h3 id="step-by-step-guide-1">Step-by-Step Guide</h3>
<ol>
<li>
<p><strong>Set Up Auth0 FGA</strong>:</p>
<ul>
<li>Go to the Auth0 dashboard and create a new FGA application.</li>
<li>Note down the API URL and credentials.</li>
</ul>
</li>
<li>
<p><strong>Install the OpenFGA SDK</strong>:</p>
<ul>
<li>
<p>Add the following to your Gemfile:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>gem <span style="color:#e6db74">&#39;openfga&#39;</span>, <span style="color:#e6db74">&#39;~&gt; 0.1&#39;</span>
</span></span></code></pre></div></li>
<li>
<p>Install the gem:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>bundle install
</span></span></code></pre></div></li>
</ul>
</li>
<li>
<p><strong>Configure OpenFGA in Rails</strong>:</p>
<ul>
<li>
<p>Create a new initializer file <code>config/initializers/openfga.rb</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">OpenFGA</span><span style="color:#f92672">.</span>configure <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>config<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>api_url <span style="color:#f92672">=</span> <span style="color:#66d9ef">ENV</span><span style="color:#f92672">[</span><span style="color:#e6db74">&#39;OPENFGA_API_URL&#39;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>client_id <span style="color:#f92672">=</span> <span style="color:#66d9ef">ENV</span><span style="color:#f92672">[</span><span style="color:#e6db74">&#39;OPENFGA_CLIENT_ID&#39;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>  config<span style="color:#f92672">.</span>client_secret <span style="color:#f92672">=</span> <span style="color:#66d9ef">ENV</span><span style="color:#f92672">[</span><span style="color:#e6db74">&#39;OPENFGA_CLIENT_SECRET&#39;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div></li>
</ul>
</li>
<li>
<p><strong>Set Environment Variables</strong>:</p>
<ul>
<li>
<p>Add your OpenFGA credentials to your <code>.env</code> file:</p>



<div class="goat svg-container ">
  
    <svg
      xmlns="http://www.w3.org/2000/svg"
      font-family="Menlo,Lucida Console,monospace"
      
        viewBox="0 0 392 57"
      >
      <g transform='translate(8,16)'>
<text text-anchor='middle' x='0' y='4' fill='currentColor' style='font-size:1em'>O</text>
<text text-anchor='middle' x='0' y='20' fill='currentColor' style='font-size:1em'>O</text>
<text text-anchor='middle' x='0' y='36' fill='currentColor' style='font-size:1em'>O</text>
<text text-anchor='middle' x='8' y='4' fill='currentColor' style='font-size:1em'>P</text>
<text text-anchor='middle' x='8' y='20' fill='currentColor' style='font-size:1em'>P</text>
<text text-anchor='middle' x='8' y='36' fill='currentColor' style='font-size:1em'>P</text>
<text text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'>E</text>
<text text-anchor='middle' x='16' y='20' fill='currentColor' style='font-size:1em'>E</text>
<text text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'>E</text>
<text text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'>N</text>
<text text-anchor='middle' x='24' y='20' fill='currentColor' style='font-size:1em'>N</text>
<text text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'>N</text>
<text text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'>F</text>
<text text-anchor='middle' x='32' y='20' fill='currentColor' style='font-size:1em'>F</text>
<text text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'>F</text>
<text text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'>G</text>
<text text-anchor='middle' x='40' y='20' fill='currentColor' style='font-size:1em'>G</text>
<text text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'>G</text>
<text text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'>A</text>
<text text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'>A</text>
<text text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'>A</text>
<text text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'>A</text>
<text text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'>C</text>
<text text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'>C</text>
<text text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'>P</text>
<text text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'>L</text>
<text text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'>L</text>
<text text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'>I</text>
<text text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'>I</text>
<text text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'>I</text>
<text text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'>E</text>
<text text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'>E</text>
<text text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'>U</text>
<text text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'>N</text>
<text text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'>N</text>
<text text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'>R</text>
<text text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'>T</text>
<text text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'>T</text>
<text text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'>L</text>
<text text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'>=</text>
<text text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'>I</text>
<text text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'>S</text>
<text text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'>h</text>
<text text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'>D</text>
<text text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'>E</text>
<text text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'>=</text>
<text text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'>C</text>
<text text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'>y</text>
<text text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'>R</text>
<text text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'>E</text>
<text text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'>T</text>
<text text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'>:</text>
<text text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'>=</text>
<text text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'>/</text>
<text text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'>y</text>
<text text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'>/</text>
<text text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='200' y='20' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='208' y='20' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='216' y='20' fill='currentColor' style='font-size:1em'>f</text>
<text text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='224' y='20' fill='currentColor' style='font-size:1em'>g</text>
<text text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='232' y='20' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='240' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='240' y='20' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'>f</text>
<text text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'>f</text>
<text text-anchor='middle' x='256' y='20' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'>g</text>
<text text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'>g</text>
<text text-anchor='middle' x='264' y='20' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='272' y='20' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='280' y='20' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='288' y='20' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='288' y='36' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'>x</text>
<text text-anchor='middle' x='296' y='20' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='296' y='36' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='304' y='20' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='304' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='312' y='20' fill='currentColor' style='font-size:1em'>d</text>
<text text-anchor='middle' x='312' y='36' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='320' y='36' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='328' y='36' fill='currentColor' style='font-size:1em'>_</text>
<text text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='336' y='36' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='344' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='352' y='36' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='360' y='36' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='368' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='376' y='36' fill='currentColor' style='font-size:1em'>t</text>
</g>

    </svg>
  
</div>
</li>
</ul>
</li>
<li>
<p><strong>Implement FgaService</strong>:</p>
<ul>
<li>
<p>Create a service <code>app/services/fga_service.rb</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">FgaService</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">self</span><span style="color:#f92672">.</span><span style="color:#a6e22e">get_allowed_documents</span>(user_id)
</span></span><span style="display:flex;"><span>    client <span style="color:#f92672">=</span> <span style="color:#66d9ef">OpenFGA</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Client</span><span style="color:#f92672">.</span>new
</span></span><span style="display:flex;"><span>    response <span style="color:#f92672">=</span> client<span style="color:#f92672">.</span>read(
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">type</span>: <span style="color:#e6db74">&#39;document&#39;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">relation</span>: <span style="color:#e6db74">&#39;viewer&#39;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">user</span>: <span style="color:#e6db74">&#34;user:</span><span style="color:#e6db74">#{</span>user_id<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    )
</span></span><span style="display:flex;"><span>    response<span style="color:#f92672">.</span>objects<span style="color:#f92672">.</span>map { <span style="color:#f92672">|</span>obj<span style="color:#f92672">|</span> obj<span style="color:#f92672">.</span>split(<span style="color:#e6db74">&#39;:&#39;</span>)<span style="color:#f92672">.</span>last }
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div></li>
</ul>
</li>
<li>
<p><strong>Update RagQueryService</strong>:</p>
<ul>
<li>
<p>Modify <code>app/services/rag_query_service.rb</code> to filter documents based on user permissions:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">RagQueryService</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">initialize</span>(user_id)
</span></span><span style="display:flex;"><span>    @user_id <span style="color:#f92672">=</span> user_id
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">query</span>(question)
</span></span><span style="display:flex;"><span>    allowed_document_ids <span style="color:#f92672">=</span> <span style="color:#66d9ef">FgaService</span><span style="color:#f92672">.</span>get_allowed_documents(@user_id)
</span></span><span style="display:flex;"><span>    chunks <span style="color:#f92672">=</span> <span style="color:#66d9ef">DocumentChunk</span><span style="color:#f92672">.</span>where(<span style="color:#e6db74">document_id</span>: allowed_document_ids)
</span></span><span style="display:flex;"><span>    embeddings <span style="color:#f92672">=</span> chunks<span style="color:#f92672">.</span>pluck(<span style="color:#e6db74">:vector</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Perform vector search and augmentation</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Send to LLM for generation</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div></li>
</ul>
</li>
<li>
<p><strong>Integrate with Controllers</strong>:</p>
<ul>
<li>
<p>Ensure the user ID is passed to <code>RagQueryService</code>. For example, in <code>app/controllers/chats_controller.rb</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ChatsController</span> <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">ApplicationController</span>
</span></span><span style="display:flex;"><span>  before_action <span style="color:#e6db74">:authenticate_user!</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">create</span>
</span></span><span style="display:flex;"><span>    user_id <span style="color:#f92672">=</span> session<span style="color:#f92672">[</span><span style="color:#e6db74">:userinfo</span><span style="color:#f92672">][</span><span style="color:#e6db74">:uid</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    service <span style="color:#f92672">=</span> <span style="color:#66d9ef">RagQueryService</span><span style="color:#f92672">.</span>new(user_id)
</span></span><span style="display:flex;"><span>    response <span style="color:#f92672">=</span> service<span style="color:#f92672">.</span>query(params<span style="color:#f92672">[</span><span style="color:#e6db74">:question</span><span style="color:#f92672">]</span>)
</span></span><span style="display:flex;"><span>    render <span style="color:#e6db74">json</span>: { <span style="color:#e6db74">response</span>: response }
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">private</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">authenticate_user!</span>
</span></span><span style="display:flex;"><span>    redirect_to <span style="color:#e6db74">&#39;/auth/auth0&#39;</span> <span style="color:#66d9ef">unless</span> session<span style="color:#f92672">[</span><span style="color:#e6db74">:userinfo</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div></li>
</ul>
</li>
</ol>
<h2 id="key-takeaways">Key Takeaways</h2>
<ul>
<li><strong>Authentication</strong>: Use Auth0 to manage user identities securely.</li>
<li><strong>Authorization</strong>: Implement Auth0 FGA to enforce fine-grained access control.</li>
<li><strong>Data Integrity</strong>: Ensure that only authorized users can access specific documents, preventing data leakage.</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>Securing Ruby on Rails RAG applications is crucial to protect sensitive data. By integrating Auth0 for authentication and Auth0 FGA for fine-grained authorization, you can ensure that only authorized users access specific documents. This setup not only enhances security but also improves the user experience by providing accurate and relevant information.</p>
<div class="notice success">✅ <strong>Best Practice:</strong> Always validate user permissions before accessing sensitive data in RAG applications.</div>
<div class="key-takeaway">
<h4>🎯 Key Takeaways</h4>
<ul>
<li>Use Auth0 for secure user authentication.</li>
<li>Implement Auth0 FGA for fine-grained authorization.</li>
<li>Ensure data integrity by validating user permissions.</li>
</ul>
</div>]]></content:encoded></item></channel></rss>