Langchain Authorizer Integration

Prev Next

PlainID’s LangChain Authorizer brings policy-based decisioning to each stage of the LLM workflow, enabling you to restrict which prompts users are allowed to submit, control which documents users are authorized to retrieve from vector stores and Redact sensitive output fields based on dynamic entitlements.

By externalizing access decisions into PlainID’s centralized Policy framework, enterprises can maintain consistency with existing security and compliance practices without hardcoding rules into the application.

Ensure your PlainID Environment supports Policies that enforce prompt evaluation, data access, MCP tools, and output redaction before beginning.
For a complete walkthrough example, including a guide on how to set up these Policies and a downloadable code sample, see the LangChain Authorizer Use-case.

Refer to our overview of the Langchain Authorizer for more information.

Prerequisites

To get started, ensure that the SQL Authorizer Service has been deployed.

Follow these steps to implement the PlainID Langchain Authorizer in your Agentic AI Application:


PlainIDPermissionsProvider

Use the PlainIDPermissionsProvider to retrieve user entitlements and expose them to guardrail components in your LangChain workflow. This enables Policy-based filtering and output redaction based on user identity and context.

PlainIDPermissionsProvider is a class that retrieves user entitlements from the PlainID Policy Decision Point (PDP) and makes them available to the guardrail components.

from langchain_plainid import PlainIDPermissionsProvider
permissions_provider = PlainIDPermissionsProvider(
    base_url="https://plainid.example.com",
    client_id="CLIENT_ID",
    client_secret="CLIENT_SECRET",
    entity_id="USER_ID",
    entity_type_id="User"
)

Parameters

Parameter Description
base_url The base URL used by the LangChain Authorizer to evaluate Policies.
clientId The Client ID used by the LangChain Authorizer to authenticate with the PlainID.
clientSecret The Client Secret used to authenticate with the PlainID.
entityId The unique identifier of the identity (e.g., user ID) making the LangChain request.
entityTypeId The Identity Template (e.g., User, ServiceAccount) associated with the entityId. Required if a full user object is not provided.

Note: The Categorizer and Anonymizer components utilize this internally for PlainID integration.


Guardrail 1: Prompt Categorization in PlainID

The objective of this guardrail is to validate whether the user is authorized to ask about the topic by classifying the prompt and checking it against PlainID Policies.

LLM-Based Prompt Classification

The PlainIDCategorizer acts as a pre-query enforcement layer. It uses the LLMCategoryClassifierProvider to map prompts to semantic categories (e.g., billing, security, product_support) using an underlying LLM (e.g., Ollama, OpenAI).

This abstraction supports both local and API-based language models and enables model-agnostic prompt categorization. The resulting category is then validated against the Policies configured in PlainID.

Note: Use high-quality models for more accurate classification results.

To classify the prompt:
2) Set up your language model for prompt classification:

from langchain_community.llms import Ollama

llm = Ollama(model="llama3", temperature=0)

Note: You can use any supported model, not just LLaMA. Choose one that fits your performance and privacy requirements. The categorization result highlight depends on the LLM used.

  1. Enforce Prompt Categorization in your application code:
from langchain_plainid.classification import LLMCategoryClassifierProvider
from langchain_plainid import PlainIDCategorizer

# Step 1: Initialize the LLM-based classifier
classifier = LLMCategoryClassifierProvider(llm=my_llm)

# Step 2: Initialize the categorizer
categorizer = PlainIDCategorizer(
    classifier_provider=classifier,
    permissions_provider=permissions_provider
)

# Step 3: Categorize and authorize the prompt
try:
    category = categorizer.invoke(prompt)
    print(f"[Gate 1: ALLOWED] Query categorized as '{category}', proceeding.")
except ValueError as e:
    print(f"[Gate 1: DENIED] {e}")
    print("→ Response:\nYou’re not authorized to ask about these topics.")

Guardrail 2: RAG Data Control

  1. RAG Control in PlainID
    The PlainIDRetriever enforces fine-grained access control during vector store searches by injecting dynamic filters based on user context and PlainID Policies. This prevents unauthorized access to documents, even when results are semantically relevant.

For example, a support analyst located in the EU may only retrieve documents tagged with region=eu-central, even if U.S. documents match the query intent.

LangChain integrates with vector databases such as Chroma, FAISS, and Weaviate to perform semantic searches across embedded documents. These documents must be enriched with structured metadata (e.g., region, topic) to enable Policy-based filtering.

⚠️ Note: LangChain’s query filter translator supports a subset of vector stores. Compatibility should be validated per use case and tested with Chroma and FAISS.

  1. Enforce RAG Control (Guardrail 2) in your application code:
from langchain_community.vectorstores import Chroma
from langchain_core.documents import Document
from langchain_core.embeddings import FakeEmbeddings
from langchain_plainid import PlainIDRetriever
from langchain_plainid.providers import PlainIDFilterProvider

# Step 1: Define your vector store
docs = [...]  # Pre-tagged documents with metadata like 'region', 'topic'
vector_store = Chroma.from_documents(documents=docs, embedding=FakeEmbeddings())

# Step 2: Initialize the filter provider
filter_provider = PlainIDFilterProvider(
    base_url="https://plainid.example.com",
    client_id="plainid-client",
    client_secret="plainid-client-secret",
    entity_id="user-id",
    entity_type_id="User"
)

# Step 3: Wrap the retriever with policy enforcement
policy_enforced_retriever = PlainIDRetriever(
    vectorstore=vector_store,
    filter_provider=filter_provider
)

# Step 4: Execute a query
filtered_docs = policy_enforced_retriever.invoke("Show me outage reports in Europe")

Guardrail 3: Define Output Redaction in PlainID

Prevent unauthorized exposure of sensitive or personally identifiable information (PII) in model-generated responses using the PlainIDAnonymizer. This component masks or encrypts output fields based on user-specific entitlements, even if generated by the model.

The PlainIDAnonymizer inspects the final output and dynamically applies redaction rules, masking or encrypting specified fields (required to choose at least one action), based on Policies defined in PlainID. This acts as a final guardrail, ensuring sensitive content does not reach unauthorized users regardless of what the LLM produces.

  1. Anonymize Sensitive Output in your application code:
from langchain_plainid import PlainIDAnonymizer

# Initialize the anonymizer with a permissions provider
plainid_anonymizer = PlainIDAnonymizer(
    permissions_provider=permissions_provider,
    encrypt_key="your_encryption_key"  # Optional, only required if using ENCRYPT
)

# Redact sensitive fields in the model's answer
final_output = plainid_anonymizer.invoke(answer)

Note: The categories need to be aligned with Presidio. The list of possible anonymization sources are based on PII entities. We are use the Microsoft Presidio library to detect PII entities in your text. You can find the list of supported entities here.

Native Integration with the SQL Authorizer

The SQL Authorizer allows applications to send SQL queries to PlainID for policy evaluation before execution. Based on the configured Policies, the SQL Authorizer may modify the query to enforce data access controls and return a policy-compliant SQL statement.

Setup

To use the SQL Authorizer, obtain the following from your PlainID deployment:

  • SQL Authorizer service base URL (for example: https://your-sql-authz.plainid.cloud)
  • Client ID for authentication
  • Client Secret or a JWT token for authentication (at least one is required)

Authentication

The client supports two authentication methods:

  • Client credentials – provide client_id and client_secret when initializing the client.
  • JWT token – provide an auth_token with each request. The Bearer prefix is added automatically if it is not included.

Authorizing a SQL Query

Use the PlainIDSQLAuthorizer to send a SQL statement to the PlainID SQL Authorizer service and receive an authorized query. See the parameters and code format below:

Request Parameters

The SQL Authorizer returns the policy-enforced SQL query, which can then be executed by your database client.

Parameter Type Required Description
sql str Yes The SQL query to authorize and enforce policies on.
entity_id str No The identifier of the entity (for example, a user ID) used for policy evaluation.
entity_type_id str No The identity template associated with the entity (for example, User).
user str No Optional user identification string.
flags SQLAuthorizerFlags No Optional configuration that controls SQL modification behavior.
entity_attributes dict No Additional attributes associated with the entity that may be used during policy evaluation.
context_data dict No Additional contextual data passed to the policy evaluation request.
environment dict No Environment-specific data used during policy evaluation.
runtime_fine_tune SQLAuthorizerRuntimeFineTune No Optional parameters used to adjust policy decision resolution at runtime.

Request Flags

Flag Type Description
empty_rls_treat_as_denied bool Treat empty row-level security policies as denied.
empty_cls_treat_as_permitted bool Treat empty column-level security policies as permitted.
ignore_runtime_cls_response bool Ignore runtime column-level security responses from the policy engine.
expand_star_column bool Expand * in the query into explicit column names when applying policies.
opposite_column_filtering_behavior bool Apply the opposite behavior for column filtering during enforcement.
policies_join_operation PoliciesJoinOperation Defines how multiple policies are combined (OR or AND).
runtime_cls_as_masked bool Treat runtime column-level security results as masked values.
columns_resource_type str Resource type used when evaluating column-level policies.

Code Format

from langchain_plainid import (
    PlainIDSQLAuthorizer,
    SQLAuthorizerFlags,
    SQLAuthorizerRequest,
)
from langchain_plainid.models.sql_authorizer_models import PoliciesJoinOperation

sql_authorizer = PlainIDSQLAuthorizer(
    base_url="https://your-sql-authz.plainid.cloud",
    client_id="your_client_id",
    client_secret="your_client_secret",
)

request = SQLAuthorizerRequest(
    sql="SELECT * FROM accounts WHERE country = 'US'",
    entity_id="your_entity_id",
    entity_type_id="User",
    flags=SQLAuthorizerFlags(
        empty_rls_treat_as_denied=True,
        empty_cls_treat_as_permitted=True,
        expand_star_column=True,
        policies_join_operation=PoliciesJoinOperation.OR,
    ),
)

response = sql_authorizer.authorize_sql(request)
print(response.sql)           # The modified SQL query
print(response.was_modified)  # True if policies were applied
print(response.error)         # Empty string if no errors

Using a JWT token instead of client secret

sql_authorizer = PlainIDSQLAuthorizer(
    base_url="https://your-sql-authz.plainid.cloud",
    client_id="your_client_id",
)

response = sql_authorizer.authorize_sql(request, auth_token="your_jwt_token")

For a practical demonstration of these capabilities and a detailed walkthrough of a real-world implementation, refer to the Langchain Authorizer Use-case documentation.

© 2025 PlainID LTD. All rights reserved.