{
  "version": 3,
  "sources": ["ssg:https://framerusercontent.com/modules/pMOkqe0AI2ltf8j2prY4/H9keC3sqYImp4pKzibfm/yXY2jAeSE-3.js"],
  "sourcesContent": ["import{jsx as e,jsxs as t}from\"react/jsx-runtime\";import{ComponentPresetsConsumer as i,Link as n}from\"framer\";import{motion as a}from\"framer-motion\";import*as r from\"react\";import o from\"https://framerusercontent.com/modules/pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js\";export const richText=/*#__PURE__*/t(r.Fragment,{children:[/*#__PURE__*/e(\"p\",{children:\"When building a FastAPI application, handling parameters correctly is crucial to ensure that your endpoints function as expected. FastAPI makes it easy to work with both request headers and query parameters, allowing you to create flexible and powerful APIs. In this article, we'll explore how to handle parameters as headers or query parameters in FastAPI, and when you might want to use each method.\"}),/*#__PURE__*/e(\"h3\",{children:\"What are Query Parameters and Headers?\"}),/*#__PURE__*/e(\"p\",{children:\"Before diving into the code, let's clarify some key terms:\"}),/*#__PURE__*/e(\"p\",{children:'- Query Parameters: These are part of the URL in a request. They typically follow the \"?\" symbol in the query string and are used to filter or modify the response from the server. For example, in the URL `https://example.com/items?category=books&limit=10`, `category` and `limit` are query parameters.'}),/*#__PURE__*/e(\"p\",{children:\"  - Headers: Request headers are key-value pairs sent with the HTTP request or response, carrying information like content type, authentication tokens, and more. Unlike query parameters, headers are not visible in the URL and are instead part of the HTTP request metadata, also known as HTTP headers.\"}),/*#__PURE__*/e(\"h3\",{children:\"Handling Query Parameters in FastAPI\"}),/*#__PURE__*/e(\"p\",{children:\"Query parameters are straightforward to handle in FastAPI. Let's say you want to create an endpoint in your FastAPI application that retrieves items, and you want to filter these items based on a `category` query parameter and limit the number of items returned with a `limit` query parameter.\"}),/*#__PURE__*/e(\"p\",{children:\"Here's how you can do it:\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'from fastapi import FastAPI\\nfrom typing import Optional\\napp = FastAPI()\\n\\n@app.get(\"/items/\")\\nasync def get_items(category: Optional[str] = None, limit: int = 10):\\n    items = [{\"item_id\": 1, \"category\": \"books\"}, {\"item_id\": 2, \"category\": \"electronics\"}]\\n    if category:\\n        items = [item for item in items if item[\"category\"] == category]\\n    return items[:limit]',language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:\"In this example:\"}),/*#__PURE__*/t(\"p\",{children:[\"- \",/*#__PURE__*/e(\"code\",{children:\"category\"}),\" is an optional query parameter. If it\u2019s not provided, it defaults to `None`.\"]}),/*#__PURE__*/t(\"p\",{children:[\"- \",/*#__PURE__*/e(\"code\",{children:\"limit\"}),\" is another query parameter with a default value of `10`.\"]}),/*#__PURE__*/t(\"p\",{children:[\"When you make a request to \",/*#__PURE__*/e(\"code\",{children:\"/items?category=books&limit=2\"}),\", FastAPI will filter the items by the `books` category and return only 2 items. This demonstrates how you can handle request parameters that come through the query string.\"]}),/*#__PURE__*/e(\"h3\",{children:\"Handling Headers in FastAPI\"}),/*#__PURE__*/t(\"p\",{children:[\"Sometimes, you need to extract information from the request headers. FastAPI makes this easy as well. Let\u2019s modify our previous example to require an \",/*#__PURE__*/e(\"code\",{children:\"X-Token\"}),\" HTTP header, which might be used for simple authentication.\"]}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'from fastapi import FastAPI, Header, HTTPException\\napp = FastAPI()\\n\\n@app.get(\"/items/\")\\nasync def get_items(category: Optional[str] = None, limit: int = 10, x_token: str = Header(...)):\\n    if x_token != \"supersecrettoken\":\\n        raise HTTPException(status_code=400, detail=\"Invalid X-Token header\")\\n    items = [{\"item_id\": 1, \"category\": \"books\"}, {\"item_id\": 2, \"category\": \"electronics\"}]\\n    if category:\\n        items = [item for item in items if item[\"category\"] == category]\\n    return items[:limit]',language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:\"In this case:\"}),/*#__PURE__*/t(\"p\",{children:[\"- The \",/*#__PURE__*/e(\"code\",{children:\"x_token\"}),\" HTTP header is required for the request. If it doesn\u2019t match the expected value, FastAPI returns an error.\"]}),/*#__PURE__*/t(\"p\",{children:[\"- The \",/*#__PURE__*/e(\"code\",{children:\"Header\"}),\" function is used to extract the \",/*#__PURE__*/e(\"code\",{children:\"X-Token\"}),\" header from the incoming request.\"]}),/*#__PURE__*/t(\"p\",{children:[\"When a request is made to \",/*#__PURE__*/e(\"code\",{children:\"/items\"}),\" with the header \",/*#__PURE__*/e(\"code\",{children:\"X-Token: supersecrettoken\"}),\", the server processes the request normally. Otherwise, it raises an HTTP exception.\"]}),/*#__PURE__*/e(\"h3\",{children:\"When to Use Query Parameters vs. Headers\"}),/*#__PURE__*/t(\"p\",{children:[\"- \",/*#__PURE__*/e(\"strong\",{children:\"Use Query Parameters\"}),\" when you want to filter or sort data. Query parameters are ideal for optional query parameters that modify the response, like search filters, pagination limits, or sorting criteria.\"]}),/*#__PURE__*/t(\"p\",{children:[\"- \",/*#__PURE__*/e(\"strong\",{children:\"Use Headers\"}),\" for metadata that affects how the request is processed but doesn\u2019t directly modify the resource being fetched. Request headers are commonly used for passing authentication tokens, content type, and custom user agents.\"]}),/*#__PURE__*/e(\"h3\",{children:\"Combining Query Parameters and Headers\"}),/*#__PURE__*/e(\"p\",{children:\"In many cases, you\u2019ll need to handle both query parameters and headers in the same endpoint. FastAPI allows you to do this seamlessly. Here\u2019s an example that combines both:\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'from fastapi import FastAPI, Header, HTTPException, Query\\nfrom typing import Optional\\napp = FastAPI()\\n\\n@app.get(\"/items/\")\\nasync def get_items(\\n    category: Optional[str] = Query(None), \\n    limit: int = Query(10),\\n    x_token: str = Header(...)\\n):\\n    if x_token != \"supersecrettoken\":\\n        raise HTTPException(status_code=400, detail=\"Invalid X-Token header\")\\n    \\n    items = [{\"item_id\": 1, \"category\": \"books\"}, {\"item_id\": 2, \"category\": \"electronics\"}]\\n    \\n    if category:\\n        items = [item for item in items if item[\"category\"] == category]\\n    \\n    return items[:limit]',language:\"JSX\"})})}),/*#__PURE__*/t(\"p\",{children:[\"Here, we use \",/*#__PURE__*/e(\"code\",{children:\"Query\"}),\" to define query parameters and \",/*#__PURE__*/e(\"code\",{children:\"Header\"}),\" to handle the header. This method allows you to have clean, readable code while ensuring that your API handles requests securely and efficiently.\"]}),/*#__PURE__*/e(\"h3\",{children:\"Handling Path Parameters in FastAPI\"}),/*#__PURE__*/t(\"p\",{children:[\"Along with query parameters and headers, FastAPI also allows you to work with path parameters. Path parameters are part of the URL path and are often used to identify specific resources. For example, in the URL \",/*#__PURE__*/e(\"code\",{children:\"/items/{item_id}\"}),\", \",/*#__PURE__*/e(\"code\",{children:\"item_id\"}),\" is a path parameter.\"]}),/*#__PURE__*/e(\"p\",{children:\"Here's how you can handle path parameters along with query parameters and headers:\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'from fastapi import FastAPI, Header, HTTPException, Query, Path\\napp = FastAPI()\\n\\n@app.get(\"/items/{item_id}\")\\nasync def get_item(\\n    item_id: int = Path(..., title=\"The ID of the item to get\"),\\n    category: Optional[str] = Query(None), \\n    limit: int = Query(10),\\n    x_token: str = Header(...)\\n):\\n    if x_token != \"supersecrettoken\":\\n        raise HTTPException(status_code=400, detail=\"Invalid X-Token header\")\\n    \\n    items = [{\"item_id\": item_id, \"category\": \"books\"}]\\n    \\n    if category:\\n        items = [item for item in items if item[\"category\"] == category]\\n    \\n    return items[:limit]',language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:\"In this example:\"}),/*#__PURE__*/t(\"p\",{children:[\"- The \",/*#__PURE__*/e(\"code\",{children:\"item_id\"}),\" is a path parameter that identifies the specific item.\"]}),/*#__PURE__*/e(\"p\",{children:\"- The query parameters and headers are handled similarly to the previous examples, but now they are combined with a path parameter.\"}),/*#__PURE__*/e(\"h3\",{children:\"Conclusion\"}),/*#__PURE__*/e(\"p\",{children:\"FastAPI makes it simple to work with query parameters, request headers, and path parameters, offering flexibility and clarity in your code. Whether you're filtering results with query parameters, securing requests with headers, or identifying resources with path parameters, FastAPI provides the tools you need to build robust and flexible APIs. By understanding when and how to use these components, you can create cleaner, more effective endpoints for your FastAPI application.\"})]});export const richText1=/*#__PURE__*/t(r.Fragment,{children:[/*#__PURE__*/e(\"p\",{children:\"When building a React application, one of the most important decisions you\u2019ll make is how to handle authentication. Authentication is the process of verifying who a user is and ensuring they have the right permissions to access different parts of your application. A good authentication flow not only keeps your app secure but also provides a smooth experience for users. With so many options out there, it can be tough to choose the right authentication library for your React applications. In this article, we'll break down some of the best options, including Firebase Authentication, Auth0, Clerk, ProperAuth, and Oneloop. We'll also explain why Oneloop stands out as a specialized tool for API authentication.\"}),/*#__PURE__*/e(\"h3\",{children:\"Firebase Authentication\"}),/*#__PURE__*/e(\"p\",{children:\"Firebase Authentication is a popular choice among developers, especially if you\u2019re already using Firebase for other backend services like databases or hosting. Firebase Authentication makes it easy to add a variety of authentication methods to your React application. Whether you want users to log in with an email and password, a phone number, or through social logins like Google and Facebook, Firebase has you covered.\"}),/*#__PURE__*/e(\"p\",{children:\"This service is great for small to medium-sized React applications. Firebase Authentication integrates smoothly with other Firebase services, making it a solid option if you're already in the Firebase ecosystem. It\u2019s simple to set up and comes with built-in security features that help protect your app from unauthorized access.\"}),/*#__PURE__*/e(\"h3\",{children:\"Auth0\"}),/*#__PURE__*/e(\"p\",{children:\"Auth0 is another powerful option for adding authentication to your React applications. It\u2019s known for being robust and scalable, making it a good fit for larger applications that require advanced security features. With Auth0, you can easily implement social logins, multi-factor authentication, and single sign-on (SSO). \"}),/*#__PURE__*/e(\"p\",{children:\"Auth0\u2019s React SDK includes components and hooks that make it easy to manage authentication in your app. You can protect routes, manage user sessions, and display user information with just a few lines of code. While Auth0 offers a lot of powerful features, it might be more than you need if you\u2019re building a smaller app that doesn\u2019t require such extensive functionality.\"}),/*#__PURE__*/e(\"h3\",{children:\"Clerk\"}),/*#__PURE__*/e(\"p\",{children:\"Clerk is a newer option in the authentication space, but it\u2019s quickly gaining popularity because of its modern approach. Clerk is designed to provide a smooth, user-friendly experience with pre-built authentication UIs, user management, and support for custom authentication flows.\"}),/*#__PURE__*/e(\"p\",{children:\"Clerk\u2019s React components integrate easily into your application, making it a great choice if you want a hassle-free setup. It supports a wide range of authentication methods, including passwordless logins, social logins, and traditional email/password combinations. This flexibility makes Clerk a strong choice for developers who want a seamless authentication experience without a lot of manual configuration.\"}),/*#__PURE__*/e(\"h3\",{children:\"ProperAuth\"}),/*#__PURE__*/e(\"p\",{children:\"ProperAuth is another excellent option for developers who need a flexible and easy-to-use authentication library for their React applications. ProperAuth stands out for its customization options, allowing you to tailor the authentication flow to fit your specific needs. It supports multiple authentication providers and offers a robust API for managing user sessions and permissions.\"}),/*#__PURE__*/e(\"p\",{children:\"With ProperAuth, you can integrate authentication into your app with ease, whether you\u2019re building a simple project or a complex system with multiple authentication requirements. It\u2019s an ideal choice if you need more control over the authentication process while still benefiting from pre-built components that speed up development.\"}),/*#__PURE__*/e(\"h3\",{children:\"Oneloop: Specialized for API Authentication\"}),/*#__PURE__*/e(\"p\",{children:\"While the libraries mentioned above focus on user authentication, Oneloop is built specifically for API authentication. This makes it unique, especially for developers who are building React applications that need to interact with APIs securely.\"}),/*#__PURE__*/e(\"p\",{children:\"Oneloop offers an embeddable React UI component that lets users manage API keys directly within your React application. This feature is incredibly useful for apps that need to handle API keys securely, providing an easy way for users to generate, view, and revoke keys without leaving your app. \"}),/*#__PURE__*/e(\"p\",{children:\"Oneloop\u2019s focus on API authentication makes it the perfect choice for applications that require secure interactions with multiple APIs. Whether you\u2019re building a developer tool, an API management platform, or any other app that relies on secure API communication, Oneloop provides the specialized tools you need to get the job done.\"}),/*#__PURE__*/e(\"h2\",{children:\"Conclusion\"}),/*#__PURE__*/e(\"p\",{children:\"Choosing the right authentication library for your React application can make a big difference in how secure and user-friendly your app is. Firebase Authentication, Auth0, Clerk, and ProperAuth are all great options for managing user authentication in different types of applications. Each offers a unique set of features and benefits, depending on the size and complexity of your project.\"}),/*#__PURE__*/e(\"p\",{children:\"However, if your React application requires strong API authentication, Oneloop is the tool you need. Oneloop\u2019s specialized focus on API security, along with its embeddable React component for managing API keys, ensures that your APIs are secure and easy to manage for your users. \"}),/*#__PURE__*/e(\"p\",{children:\"No matter which library you choose, integrating a solid authentication solution will help you build a more secure, reliable, and user-friendly React application.\"})]});export const richText2=/*#__PURE__*/t(r.Fragment,{children:[/*#__PURE__*/e(\"p\",{children:\"In today\u2019s fast-paced digital landscape, securing your APIs is not just a necessity but a critical component of your application's architecture. Developers need authentication solutions that are not only robust and secure but also easy to integrate and maintain. While Keycloak has long been a popular choice, offering a wide array of features, Oneloop provides a more streamlined, developer-friendly approach that is specifically tailored for modern API authentication. Here\u2019s why Oneloop is the superior choice when it comes to securing your APIs.\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h3\",{children:\"1. Simplified Integration\"}),/*#__PURE__*/e(\"p\",{children:\"One of the most significant challenges with Keycloak is its complexity. Setting up the keycloak server, navigating the keycloak admin console, and managing numerous environment variables can be a daunting task, especially for smaller teams or those new to the platform. Oneloop, by contrast, is designed with simplicity in mind. The platform allows developers to integrate authentication into their APIs with minimal configuration and hassle, cutting down on the time and resources required to get up and running.\"}),/*#__PURE__*/e(\"p\",{children:\"Oneloop also offers built-in support for newer frameworks such as FastAPI and Express, as well as popular languages like Go, TypeScript, Python, and more. This makes adoption easier for modern development teams, allowing them to leverage their existing tech stack without needing to implement custom solutions or workarounds.\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h3\",{children:\"2. Comprehensive API Key Management\"}),/*#__PURE__*/e(\"p\",{children:\"API keys remain a popular method for authenticating requests between servers, particularly in server-to-server communications where user-centric features like social login and user federation are not required. While Keycloak\u2019s powerful feature set includes capabilities that extend far beyond the needs of simple API key management, Oneloop offers a more focused and efficient solution. Oneloop\u2019s API key management is robust and streamlined, making it easier for developers to secure their APIs without dealing with the additional complexity that Keycloak might introduce.\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h3\",{children:\"3. Robust Authentication Features Out of the Box\"}),/*#__PURE__*/e(\"p\",{children:\"Oneloop is designed to go beyond the basics of API authentication by offering a suite of built-in features that enhance security and control. These include:\"}),/*#__PURE__*/e(\"p\",{children:\"- Rate Limiting: Protect your APIs from abuse by controlling the number of requests that can be made within a certain timeframe. Oneloop\u2019s rate-limiting features are easy to configure and essential for maintaining the health of your services.\"}),/*#__PURE__*/e(\"p\",{children:\"- Permissions Management: Oneloop allows you to easily define and manage permissions, ensuring that only authorized users or services can access specific parts of your API. This feature is crucial for maintaining strict control over who can do what within your system.\"}),/*#__PURE__*/e(\"p\",{children:\"- IP Restrictions: For added security, Oneloop allows you to restrict access to your APIs based on IP addresses. This is particularly useful for preventing unauthorized access and ensuring that your APIs are only accessible from trusted sources.\"}),/*#__PURE__*/e(\"p\",{children:\"- Usage Analytics: Understanding how your APIs are being used is vital for both security and performance optimization. Oneloop provides detailed usage analytics, giving you insights into how often your APIs are accessed, by whom, and under what conditions. This data can be invaluable for making informed decisions about scaling, security, and feature development.\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"p\",{children:\"These features come standard with Oneloop, providing you with a robust security framework right out of the box. In contrast, achieving similar functionality with Keycloak often requires extensive configuration and a deep understanding of the platform\u2019s more complex components.\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h3\",{children:\"4. JWT Access Token Generation\"}),/*#__PURE__*/e(\"p\",{children:\"In addition to managing API keys, Oneloop also provides the ability to generate JWT (JSON Web Token) access tokens. JWTs are a versatile and secure way to manage authentication across different parts of your application, especially in scenarios involving distributed systems or microservices architectures. Oneloop makes it easy to issue and validate JWTs, allowing you to leverage the benefits of token-based authentication without needing to manage the intricacies of token generation and validation yourself. This flexibility is particularly advantageous in scenarios where both API keys and JWTs are required, such as when securing both server-to-server communication and user-facing services.\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h3\",{children:\"5. Enhanced Authorization and Access Control\"}),/*#__PURE__*/e(\"p\",{children:\"While Keycloak offers comprehensive authorization services, including support for OpenID Connect and fine-grained access control through RBAC (Role-Based Access Control), these features can be overwhelming to configure and manage, particularly for teams that are new to the platform. Oneloop simplifies the process by offering a more intuitive approach to authorization, making it easy to set up and manage permissions, roles, and access controls. This means that even complex authorization scenarios can be implemented quickly and without the steep learning curve associated with Keycloak.\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h3\",{children:\"6. Focus on API Security\"}),/*#__PURE__*/e(\"p\",{children:\"Keycloak is designed with a broad range of use cases in mind, including user authentication, social login, and user federation. However, these features, while powerful, can introduce unnecessary complexity if your primary focus is securing APIs. Oneloop is purpose-built for API security, offering a leaner, more focused toolset that allows you to secure your APIs without the overhead of managing user identities, social logins, or other user-centric features. This makes Oneloop a more efficient choice for teams whose primary concern is API security.\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h3\",{children:\"7. Better Support and Community\"}),/*#__PURE__*/e(\"p\",{children:\"Keycloak, backed by Red Hat, has a strong community and extensive documentation. However, its complexity can sometimes make finding the right support a challenge. Oneloop, with its developer-centric approach, provides clearer documentation, more focused support, and a community that is dedicated to simplifying API authentication. This ensures that you\u2019ll have the resources and assistance you need to implement and maintain your API security without the frustrations that can come with navigating a more complex platform like Keycloak.\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h2\",{children:\"Conclusion\"}),/*#__PURE__*/e(\"p\",{children:\"While Keycloak is undoubtedly a powerful tool, its broad focus and complex feature set can make it overkill for many API authentication needs, particularly when simplicity, ease of use, and a focus on API security are paramount. Oneloop offers a more streamlined, developer-friendly alternative that still provides the robust features you need to secure your APIs effectively. With built-in rate limiting, permissions management, IP restrictions, usage analytics, and the ability to generate JWT access tokens, Oneloop provides a comprehensive solution that accelerates your time to market while ensuring that your APIs remain secure, scalable, and fully monitored.\"}),/*#__PURE__*/e(\"p\",{children:\"By choosing Oneloop over Keycloak, you're opting for a solution that puts developers first, reduces complexity, and empowers your team to focus on what they do best: building great applications. Whether you\u2019re managing API keys, generating JWTs, or implementing advanced security features, Oneloop offers the tools you need to secure your APIs with confidence.\"})]});export const richText3=/*#__PURE__*/t(r.Fragment,{children:[/*#__PURE__*/e(\"p\",{children:\"FastAPI is an increasingly popular framework for building APIs in Python due to its speed, simplicity, and powerful features. One of its key features is the ability to easily add middleware, which allows you to process requests and responses globally across your application. Middleware can be used for tasks such as logging, authentication, CORS handling, and more. In this article, we\u2019ll explore how to set up middleware in FastAPI and provide examples to demonstrate how it works.\"}),/*#__PURE__*/e(\"h3\",{children:\"What is Middleware?\"}),/*#__PURE__*/e(\"p\",{children:\"Middleware in FastAPI refers to a piece of code that runs before and after each request. It allows you to modify requests, responses, or perform specific actions (like logging or authentication) without altering the core business logic of your API. Middleware is executed in a defined order, so you can chain multiple middleware functions to handle different tasks.\"}),/*#__PURE__*/e(\"h3\",{children:\"Basic Middleware Setup in FastAPI\"}),/*#__PURE__*/t(\"p\",{children:[\"To set up middleware in FastAPI, you can use the \",/*#__PURE__*/e(\"code\",{children:\"add_middleware()\"}),\" method, which is available on the FastAPI app instance. The following is a basic example of middleware that logs the time taken to process each request.\"]}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'from fastapi import FastAPI, Request\\nimport time\\napp = FastAPI()\\n\\n# This middleware is installed for all handlers\\n@app.middleware(\"http\")\\nasync def log_request_time(request: Request, call_next):\\n    start_time = time.time()\\n    response = await call_next(request)\\n    process_time = time.time() - start_time\\n    print(f\"Request: {request.url} took {process_time} seconds\")\\n    return response\\n\\n@app.get(\"/\")\\nasync def read_root():\\n    return {\"message\": \"Hello World!\"}',language:\"JSX\"})})}),/*#__PURE__*/t(\"p\",{children:[\"In this example, the \",/*#__PURE__*/e(\"code\",{children:\"log_request_time\"}),\" middleware logs the time it takes to process each request. The `call_next` function is used to pass the request to the next middleware in the stack or the route handler.\"]}),/*#__PURE__*/e(\"h3\",{children:\"Adding Middleware Using Third-Party Libraries\"}),/*#__PURE__*/t(\"p\",{children:[\"FastAPI supports the integration of third-party middleware, such as the CORS middleware provided by \",/*#__PURE__*/e(\"code\",{children:\"starlette.middleware\"}),\". CORS (Cross-Origin Resource Sharing) is a security feature that restricts resources on a web page to be requested from another domain. Below is an example of adding CORS middleware to your FastAPI app.\"]}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'from fastapi import FastAPI\\nfrom fastapi.middleware.cors import CORSMiddleware\\napp = FastAPI()\\napp.add_middleware(\\n    CORSMiddleware,\\n    allow_origins=[\"*\"],  # Allow all origins\\n    allow_credentials=True,\\n    allow_methods=[\"*\"],  # Allow all methods (GET, POST, etc.)\\n    allow_headers=[\"*\"],  # Allow all headers\\n)\\n\\n@app.get(\"/\")\\nasync def read_root():\\n    return {\"message\": \"Hello, CORS is enabled!\"}',language:\"JSX\"})})}),/*#__PURE__*/t(\"p\",{children:[\"In this example, we use the \",/*#__PURE__*/e(\"code\",{children:\"add_middleware()\"}),\" method to add \",/*#__PURE__*/e(\"code\",{children:\"CORSMiddleware\"}),\" to the FastAPI application. The middleware configuration allows all origins, methods, and headers, making it suitable for development. In production, you should restrict these settings to specific domains, methods, and headers.\"]}),/*#__PURE__*/e(\"h3\",{children:\"Custom Authentication Middleware\"}),/*#__PURE__*/e(\"p\",{children:\"One common use case for middleware is to implement custom authentication logic. Below is an example of middleware that checks for an API key in the request headers.\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'from fastapi import FastAPI, Request, HTTPException\\napp = FastAPI()\\n\\n@app.middleware(\"http\")\\nasync def api_key_authentication(request: Request, call_next):\\n    api_key = request.headers.get(\"X-API-Key\")\\n    if api_key != \"your-secret-api-key\":\\n        raise HTTPException(status_code=401, detail=\"Invalid API Key\")\\n    \\n    response = await call_next(request)\\n    return response\\n\\n@app.get(\"/protected\")\\nasync def protected_route():\\n    return {\"message\": \"You are authorized!\"}',language:\"JSX\"})})}),/*#__PURE__*/t(\"p\",{children:[\"In this example, the middleware checks for the presence of a specific API key in the \",/*#__PURE__*/e(\"code\",{children:\"X-API-Key\"}),\" header. If the key is missing or incorrect, the middleware raises an \",/*#__PURE__*/e(\"code\",{children:\"HTTPException\"}),\" with a 401 status code. Otherwise, the request is passed to the next handler.\"]}),/*#__PURE__*/e(\"h3\",{children:\"Ordering of Middleware\"}),/*#__PURE__*/e(\"p\",{children:\"In FastAPI, middleware is executed in the order it is added. This means that if you add multiple middleware components, they will be executed sequentially. It\u2019s important to consider the order in which you add middleware, as it can affect the behavior of your application.\"}),/*#__PURE__*/e(\"p\",{children:\"For example, you might want to ensure that logging middleware runs first so that it captures all incoming requests, even those that are rejected by subsequent authentication middleware.\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:\"app.add_middleware(FirstMiddleware)\\napp.add_middleware(SecondMiddleware)\",language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:\"In the above example, `FirstMiddleware` will execute before `SecondMiddleware` on incoming requests, and `SecondMiddleware` will execute before `FirstMiddleware` on the way back out.\"}),/*#__PURE__*/e(\"h3\",{children:\"Example: Combining Multiple Middleware\"}),/*#__PURE__*/e(\"p\",{children:\"Let\u2019s combine several middleware components in a single FastAPI application. We\u2019ll use CORS middleware, logging middleware, and custom authentication middleware together.\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'from fastapi import FastAPI, Request, HTTPException\\nfrom fastapi.middleware.cors import CORSMiddleware\\nimport time\\n\\napp = FastAPI()\\napp.add_middleware(\\n    CORSMiddleware,\\n    allow_origins=[\"*\"],  \\n    allow_credentials=True,\\n    allow_methods=[\"*\"],  \\n    allow_headers=[\"*\"],  \\n)\\n\\n@app.middleware(\"http\")\\nasync def log_request_time(request: Request, call_next):\\n    start_time = time.time()\\n    response = await call_next(request)\\n    process_time = time.time() - start_time\\n    print(f\"Request: {request.url} took {process_time} seconds\")\\n    return response\\n\\n@app.middleware(\"http\")\\nasync def api_key_authentication(request: Request, call_next):\\n    api_key = request.headers.get(\"X-API-Key\")\\n    if api_key != \"your-secret-api-key\":\\n        raise HTTPException(status_code=401, detail=\"Invalid API Key\")\\n    response = await call_next(request)\\n    return response\\n\\n@app.get(\"/protected\")\\nasync def protected_route():\\n    return {\"message\": \"You are authorized!\"}',language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:\"In this example, CORS middleware is applied first, followed by logging middleware and then authentication middleware. This ensures that all requests are logged and authenticated after passing the CORS checks.\"}),/*#__PURE__*/e(\"h3\",{children:\"Conclusion\"}),/*#__PURE__*/e(\"p\",{children:\"Middleware in FastAPI provides a powerful mechanism for handling cross-cutting concerns like logging, security, and performance optimizations. By using both built-in and third-party middleware, you can easily scale and secure your applications. The flexibility of FastAPI allows you to customize middleware to suit your application\u2019s specific needs while maintaining clean and maintainable code. Whether you\u2019re implementing simple logging or complex authentication, FastAPI\u2019s middleware system makes it easy to manage global request processing logic.\"})]});export const richText4=/*#__PURE__*/t(r.Fragment,{children:[/*#__PURE__*/e(\"p\",{children:\"Scaling API security for high-traffic applications is a challenging yet essential task. As your application grows, the volume of requests increases, exposing your APIs to a broader range of threats and making it critical to ensure that your security measures can scale effectively. In this article, we'll explore strategies and best practices to help you scale API security for high-traffic environments, ensuring that your application remains secure and resilient under heavy load.\"}),/*#__PURE__*/e(\"h3\",{children:\"1. Implement Rate Limiting and Throttling\"}),/*#__PURE__*/e(\"p\",{children:\"Why It Matters: Without rate limiting, a high-traffic application can be overwhelmed by excessive requests, leading to denial of service (DoS) attacks, service degradation, or even crashes. Rate limiting and throttling help protect your APIs from abuse by controlling the number of requests a client can make within a specific time frame.\"}),/*#__PURE__*/e(\"p\",{children:\"How to Scale:\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Use API Gateways:\"}),\" Deploy an API gateway that supports rate limiting and throttling at scale. Solutions like AWS API Gateway, Kong, and NGINX can manage traffic efficiently across multiple endpoints.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Custom Rate Limiting:\"}),\" Implement custom rate limiting strategies that adapt to user behavior and usage patterns. For example, set stricter limits for sensitive operations and more lenient limits for read-only requests.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Distributed Rate Limiting:\"}),\" For distributed systems, use distributed rate limiting techniques to ensure consistent enforcement across multiple instances or data centers.\"]}),/*#__PURE__*/e(\"h3\",{children:\"2. Leverage Caching Mechanisms\"}),/*#__PURE__*/e(\"p\",{children:\"Why It Matters: Caching reduces the load on your API by serving frequently requested data from a cache, rather than processing the request repeatedly. This not only improves performance but also minimizes the risk of security issues arising from overloading your backend services.\"}),/*#__PURE__*/e(\"p\",{children:\"How to Scale:\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Response Caching:\"}),\" Cache the responses of non-sensitive API endpoints, such as public data or metadata, to reduce the number of requests hitting your backend servers.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Token Caching:\"}),\" Cache API tokens or credentials securely to minimize the need for repeated authentication requests, which can strain your authentication service.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Edge Caching:\"}),\" Use edge caching services like Cloudflare or AWS CloudFront to cache responses closer to the client, reducing latency and server load.\"]}),/*#__PURE__*/e(\"h3\",{children:\"3. Implement Robust Authentication and Authorization\"}),/*#__PURE__*/e(\"p\",{children:\"Why It Matters: As your application scales, the number of users and API clients increases, making it vital to ensure that only authorized users have access to your APIs. Robust authentication and authorization mechanisms are key to preventing unauthorized access.\"}),/*#__PURE__*/e(\"p\",{children:\"How to Scale:\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- OAuth2 and OpenID Connect:\"}),\" Implement scalable authentication protocols like OAuth2 and OpenID Connect, which are widely supported and designed for high-traffic applications.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- JWT Tokens:\"}),\" Use JSON Web Tokens (JWTs) for stateless authentication, allowing for easy scaling across distributed systems. Ensure that tokens are short-lived and can be revoked if compromised.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Role-Based Access Control (RBAC):\"}),\" Implement RBAC to manage permissions at scale, ensuring that users only have access to the resources and actions they're authorized for.\"]}),/*#__PURE__*/e(\"h3\",{children:\"4. Use API Keys and Scopes for Granular Access Control\"}),/*#__PURE__*/e(\"p\",{children:\"Why It Matters: API keys are a simple yet effective way to control access to your APIs. However, as your application scales, managing API keys and ensuring that they have the correct permissions becomes more challenging.\"}),/*#__PURE__*/e(\"p\",{children:\"How to Scale:\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Scoped API Keys:\"}),\" Implement scoped API keys that grant access to specific parts of your API. This minimizes the risk of over-permissioning and ensures that each client only has access to the data and operations they need.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Key Rotation and Expiry:\"}),\" Regularly rotate API keys and set expiration dates to reduce the risk of key compromise. Automate the process of key rotation and notify clients in advance of key changes.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Centralized Key Management:\"}),\" Use centralized key management solutions, such as AWS Secrets Manager or Google Cloud Secret Manager, to securely store and manage API keys at scale.\"]}),/*#__PURE__*/e(\"h3\",{children:\"5. Secure Data in Transit and at Rest\"}),/*#__PURE__*/e(\"p\",{children:\"Why It Matters: High-traffic applications often deal with large volumes of sensitive data. Ensuring that this data is protected both in transit and at rest is critical to maintaining the integrity and confidentiality of your API.\"}),/*#__PURE__*/e(\"p\",{children:\"How to Scale:\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- TLS Encryption:\"}),\" Enforce Transport Layer Security (TLS) for all API communications to protect data in transit from eavesdropping and man-in-the-middle attacks.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Data Encryption:\"}),\" Encrypt sensitive data at rest using strong encryption algorithms. Use managed encryption services provided by cloud providers to handle encryption at scale.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- HSTS Implementation:\"}),\" Implement HTTP Strict Transport Security (HSTS) to enforce HTTPS across your domain, reducing the risk of protocol downgrade attacks.\"]}),/*#__PURE__*/e(\"h3\",{children:\"6. Implement Distributed Logging and Monitoring\"}),/*#__PURE__*/e(\"p\",{children:\"Why It Matters: As your API traffic increases, so does the volume of logs and the potential for security incidents. Distributed logging and monitoring are essential for detecting and responding to security threats in real-time.\"}),/*#__PURE__*/e(\"p\",{children:\"How to Scale:\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Centralized Logging:\"}),\" Use centralized logging solutions like ELK Stack (Elasticsearch, Logstash, Kibana), Splunk, or AWS CloudWatch to aggregate logs from multiple sources and analyze them at scale.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Real-Time Monitoring:\"}),\" Implement real-time monitoring tools like Prometheus, Grafana, or Datadog to track API performance and detect anomalies.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Automated Alerts:\"}),\" Set up automated alerts for unusual patterns, such as a sudden spike in requests or repeated authentication failures, to quickly identify potential security threats.\"]}),/*#__PURE__*/e(\"h3\",{children:\"7. Regularly Perform Security Audits and Penetration Testing\"}),/*#__PURE__*/e(\"p\",{children:\"Why It Matters: Regular security audits and penetration testing help identify vulnerabilities that could be exploited as your application scales. These proactive measures are essential for maintaining the security of your API.\"}),/*#__PURE__*/e(\"p\",{children:\"How to Scale:\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Automated Security Testing:\"}),\" Integrate automated security testing tools like OWASP ZAP, Snyk, or Burp Suite into your CI/CD pipeline to catch vulnerabilities before they reach production.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Third-Party Audits:\"}),\" Engage third-party security experts to perform regular audits and penetration tests, providing an external perspective on your API's security posture.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"- Continuous Improvement:\"}),\" Use the findings from security audits and tests to continuously improve your API security practices, adapting to new threats and scaling challenges.\"]}),/*#__PURE__*/e(\"h3\",{children:\"Conclusion\"}),/*#__PURE__*/e(\"p\",{children:\"Scaling API security for high-traffic applications requires a combination of robust authentication, granular access control, encryption, and proactive monitoring. By implementing these strategies, you can protect your APIs from a wide range of threats while ensuring that your security measures can grow alongside your application. As your application scales, so must your security practices\u2014stay vigilant, regularly review your security posture, and adapt to new challenges as they arise.\"})]});export const richText5=/*#__PURE__*/t(r.Fragment,{children:[/*#__PURE__*/e(\"h1\",{children:\"10 Common API Security Vulnerabilities and How to Avoid Them\"}),/*#__PURE__*/e(\"p\",{children:\"APIs are the backbone of modern software development, enabling communication between different services and platforms. However, their widespread use also makes them a prime target for attackers. Securing APIs is crucial to protect sensitive data and ensure the integrity of your applications. In this article, we\u2019ll explore ten common API security vulnerabilities and provide strategies to avoid them.\"}),/*#__PURE__*/e(\"h4\",{children:\"1. Lack of Authentication and Authorization\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"Vulnerability\"}),\": APIs that do not enforce proper authentication and authorization allow unauthorized users to access sensitive data and operations.\"]}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"How to Avoid\"}),\":\"]}),/*#__PURE__*/e(\"p\",{children:\"- Implement strong authentication mechanisms, such as OAuth2, API keys, or JWTs.\"}),/*#__PURE__*/e(\"p\",{children:\"- Use role-based access control (RBAC) to ensure users only access resources they\u2019re authorized for.\"}),/*#__PURE__*/e(\"p\",{children:\"- Regularly audit and update your access control policies.\"}),/*#__PURE__*/e(\"h4\",{children:\"2. Insufficient Rate Limiting\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"Vulnerability:\"}),\" Without rate limiting, APIs can be overwhelmed by too many requests, leading to denial of service (DoS) attacks or service degradation.\"]}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"strong\",{children:\"How to Avoid:\"})}),/*#__PURE__*/e(\"p\",{children:\"- Implement rate limiting to control the number of requests a client can make in a given time period.\"}),/*#__PURE__*/e(\"p\",{children:\"- Use tools like API gateways to enforce rate limiting and protect against abuse.\"}),/*#__PURE__*/e(\"h4\",{children:\"3. Injection Attacks\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"Vulnerability:\"}),\" Injection attacks, such as SQL injection or command injection, occur when an attacker sends malicious data to manipulate the backend database or system.\"]}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"strong\",{children:\"How to Avoid:\"})}),/*#__PURE__*/e(\"p\",{children:\"- Use parameterized queries or ORM frameworks to prevent direct injection of user input into queries.\"}),/*#__PURE__*/e(\"p\",{children:\"- Validate and sanitize all inputs before processing.\"}),/*#__PURE__*/e(\"p\",{children:\"- Employ web application firewalls (WAFs) to detect and block suspicious requests.\"}),/*#__PURE__*/e(\"h4\",{children:\"4. Insecure Data Transmission\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"Vulnerability:\"}),\" Transmitting data over HTTP without encryption exposes sensitive information to eavesdropping and man-in-the-middle attacks.\"]}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"strong\",{children:\"How to Avoid:\"})}),/*#__PURE__*/e(\"p\",{children:\"- Always use HTTPS to encrypt data in transit.\"}),/*#__PURE__*/e(\"p\",{children:\"- Ensure that TLS certificates are up to date and correctly configured.\"}),/*#__PURE__*/e(\"p\",{children:\"- Implement HSTS (HTTP Strict Transport Security) to force HTTPS connections.\"}),/*#__PURE__*/e(\"h4\",{children:\"5. Exposure of Sensitive Data\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"Vulnerability:\"}),\" APIs that expose sensitive data, such as passwords, tokens, or personal information, can lead to severe data breaches.\"]}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"strong\",{children:\"How to Avoid:\"})}),/*#__PURE__*/e(\"p\",{children:\"- Minimize the amount of sensitive data exposed through the API.\"}),/*#__PURE__*/e(\"p\",{children:\"- Mask or redact sensitive data in API responses.\"}),/*#__PURE__*/e(\"p\",{children:\"- Use encryption to protect sensitive data both in transit and at rest.\"}),/*#__PURE__*/e(\"h4\",{children:\"6. Lack of Input Validation\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"Vulnerability:\"}),\" APIs that do not validate user input are susceptible to a wide range of attacks, including XSS (Cross-Site Scripting) and buffer overflows.\"]}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"strong\",{children:\"How to Avoid:\"})}),/*#__PURE__*/e(\"p\",{children:\"- Validate all inputs against expected formats and types.\"}),/*#__PURE__*/e(\"p\",{children:\"- Use libraries or frameworks that provide built-in input validation.\"}),/*#__PURE__*/e(\"p\",{children:\"- Implement whitelisting for acceptable input values.\"}),/*#__PURE__*/e(\"h4\",{children:\"7. Broken Authentication\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"Vulnerability:\"}),\" Weak or broken authentication mechanisms can be exploited to impersonate users and gain unauthorized access.\"]}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"strong\",{children:\"How to Avoid:\"})}),/*#__PURE__*/e(\"p\",{children:\"- Use strong password policies and enforce multi-factor authentication (MFA).\"}),/*#__PURE__*/e(\"p\",{children:\"- Regularly rotate and revoke API keys and tokens.\"}),/*#__PURE__*/e(\"p\",{children:\"- Monitor and log all authentication attempts for suspicious activity.\"}),/*#__PURE__*/e(\"h4\",{children:\"8. Improper Error Handling\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"Vulnerability:\"}),\" APIs that provide detailed error messages can inadvertently expose internal logic, stack traces, or sensitive data.\"]}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"strong\",{children:\"How to Avoid:\"})}),/*#__PURE__*/e(\"p\",{children:\"- Use generic error messages for public-facing APIs, while logging detailed errors internally.\"}),/*#__PURE__*/e(\"p\",{children:\"- Avoid exposing stack traces or internal implementation details in API responses.\"}),/*#__PURE__*/e(\"p\",{children:\"- Implement centralized logging and monitoring for error analysis.\"}),/*#__PURE__*/e(\"h4\",{children:\"9. Insecure Direct Object References (IDOR)\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"Vulnerability\"}),\": IDOR occurs when an API exposes an internal implementation object, such as a file, database key, or record, without proper authorization checks.\"]}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"strong\",{children:\"How to Avoid:\"})}),/*#__PURE__*/e(\"p\",{children:\"- Implement access control checks to ensure users can only access resources they\u2019re authorized for.\"}),/*#__PURE__*/e(\"p\",{children:\"- Use indirect references (e.g., random tokens) rather than exposing internal IDs.\"}),/*#__PURE__*/e(\"p\",{children:\"- Regularly test your API endpoints for IDOR vulnerabilities.\"}),/*#__PURE__*/e(\"h4\",{children:\"10. Lack of Logging and Monitoring\"}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"Vulnerability\"}),\": Without proper logging and monitoring, it\u2019s difficult to detect and respond to security incidents in a timely manner.\"]}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"strong\",{children:\"How to Avoid:\"})}),/*#__PURE__*/e(\"p\",{children:\"- Implement comprehensive logging for all API requests, including authentication, authorization, and data access events.\"}),/*#__PURE__*/e(\"p\",{children:\"- Use monitoring tools to detect anomalies and potential security threats in real-time.\"}),/*#__PURE__*/e(\"p\",{children:\"- Regularly review logs to identify and address potential security issues.\"}),/*#__PURE__*/e(\"h3\",{children:\"Conclusion\"}),/*#__PURE__*/e(\"p\",{children:\"APIs are a critical part of modern software architecture, and securing them should be a top priority. By addressing these ten common vulnerabilities, you can significantly reduce the risk of security breaches and protect your users' data. Implementing robust authentication, input validation, encryption, and monitoring practices are key steps toward ensuring the security of your APIs. Regularly auditing and testing your APIs for vulnerabilities will further strengthen your security posture, helping you stay ahead of potential threats.\"})]});export const richText6=/*#__PURE__*/t(r.Fragment,{children:[/*#__PURE__*/e(\"h1\",{children:\"API Key Middleware for FastApi Python\"}),/*#__PURE__*/e(\"p\",{children:\"When building secure web applications with FastAPI, verifying API keys is essential to ensure that only authorized users can access your services. The Oneloop Python SDK makes this process seamless by providing a middleware function that integrates easily into your FastAPI applications.\"}),/*#__PURE__*/e(\"h3\",{children:\"Getting Started with Oneloop Middleware\"}),/*#__PURE__*/e(\"p\",{children:\"To begin using the Oneloop middleware in your FastAPI application, you first need to install the necessary dependencies. This includes FastAPI, typing, and the Oneloop Python SDK.\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:\"pip install typing fastapi oneloop-python\",language:\"JSX\"})})}),/*#__PURE__*/t(\"p\",{children:[\"The Oneloop middleware is already defined in the \",/*#__PURE__*/e(n,{href:\"https://docs.oneloop.ai/sdk/starter-kits/fastapi\",openInNewTab:!0,smoothScroll:!1,children:/*#__PURE__*/e(\"a\",{children:\"Oneloop FastAPI Starter Documentation\"})}),\". You can refer to the documentation to integrate the middleware into your project or copy the code directly.\"]}),/*#__PURE__*/e(\"h3\",{children:\"Using Oneloop Middleware in Your FastAPI Application\"}),/*#__PURE__*/e(\"p\",{children:\"Once the middleware is set up, you can protect your routes by adding it to your FastAPI application. \"}),/*#__PURE__*/e(\"p\",{children:\"Here's an example of how to use it:\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'from fastapi import Depends, FastAPI\\n\\n# Available at https://github.com/oneloop-starter-kits/oneloop-python-fastapi-starter-kit  \\nfrom oneloop_middleware import oneloop_middleware\\napp = FastAPI()\\n\\n# Define your routes\\n@app.get(\"/\", dependencies=[Depends(oneloop_middleware())])\\nasync def read_root():\\n    return {\"Hello\": \"World\"}',language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:\"If you need to verify specific scopes and permissions, you can do so as well:\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'@app.get(\"/\", dependencies=[Depends(oneloop_middleware([{\"id\": \"profile\", \"read\": True}]))])\\nasync def read_root():\\n    return {\"Hello\": \"World\"}',language:\"JSX\"})})}),/*#__PURE__*/e(\"h3\",{children:\"Conclusion\"}),/*#__PURE__*/e(\"p\",{children:\"The Oneloop middleware simplifies API key verification in FastAPI applications by leveraging the Oneloop Python SDK. By defining scopes and permissions, you can ensure that only authorized users have access to your API routes. This middleware not only enhances security but also makes it easy to manage API keys and their associated permissions. For a quick start, reference the [Oneloop FastAPI Starter Documentation](https://docs.oneloop.ai/sdk/starter-kits/fastapi), where the middleware is fully implemented and ready to use.\"})]});export const richText7=/*#__PURE__*/t(r.Fragment,{children:[/*#__PURE__*/e(\"h1\",{children:\"API Key Verification in Express Apps\"}),/*#__PURE__*/e(\"p\",{children:\"When building secure web applications, verifying API keys is crucial to ensure that only authorized users can access your services. The Oneloop Node.js SDK makes this process seamless by providing an easy-to-use middleware function that you can integrate into your Express applications.\"}),/*#__PURE__*/e(\"h3\",{children:\"Getting Started with Oneloop Middleware\"}),/*#__PURE__*/e(\"p\",{children:\"To start using the Oneloop middleware in your Express app, you first need to install the Oneloop Node.js SDK. This SDK provides the tools necessary for interacting with Oneloop's API key verification service.\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:\"npm install @oneloop-hq/oneloop-ts\",language:\"JSX\"})})}),/*#__PURE__*/t(\"p\",{children:[/*#__PURE__*/e(\"strong\",{children:\"The Oneloop middleware is already defined in the \"}),/*#__PURE__*/e(n,{href:\"https://github.com/oneloop-starter-kits/oneloop-node-express-ts-starter-kit\",openInNewTab:!0,smoothScroll:!1,children:/*#__PURE__*/e(\"a\",{children:/*#__PURE__*/e(\"strong\",{children:\"Oneloop Node Express TypeScript Starter Kit\"})})}),/*#__PURE__*/e(\"strong\",{children:\". You can simply import this middleware into your project or copy the code directly from the repository.\"})]}),/*#__PURE__*/e(\"h3\",{children:\"Using Oneloop Middleware in Your Express App\"}),/*#__PURE__*/t(\"p\",{children:[\"Once you have the middleware in place, you can easily protect your routes by adding it to your Express application. The middleware has several key checks - valid, unexpired, not rate-limited, not usage-limited, permissions and more!\",/*#__PURE__*/e(\"br\",{}),/*#__PURE__*/e(\"br\",{}),\"Here's how you can use it:\"]}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'// Grab this key from the dashboard and define it as part of your environment\\nONELOOP_KEY=\"KEY\" ',language:\"JSX\"})})}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'// No permissions to check\\napp.post(\"/profile\", oneloopMiddleware([]), handler);',language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:\"Or, if you need to verify specific scopes:\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'// Check that we read permissions of \"profile\" scope.\\napp.post(\\n  \"/profile\",\\n  oneloopMiddleware([{ id: \"profile\", read: true }]),\\n  readProfileHandler // defined by you\\n);',language:\"JSX\"})})}),/*#__PURE__*/e(\"h3\",{children:\"Conclusion\"}),/*#__PURE__*/t(\"p\",{children:[\"The Oneloop middleware simplifies API key verification in Express applications by leveraging the Oneloop Node.js SDK. By defining scopes and permissions, you can ensure that only authorized users have access to your API routes. This middleware not only enhances security but also makes it easy to manage API keys and their associated permissions. For a quick start, reference the \",/*#__PURE__*/e(n,{href:\"https://github.com/oneloop-starter-kits/oneloop-node-express-ts-starter-kit\",openInNewTab:!0,smoothScroll:!1,children:/*#__PURE__*/e(\"a\",{children:\"Oneloop Node Express TypeScript Starter Kit\"})}),\", where the middleware is fully implemented and ready to use.\"]})]});export const richText8=/*#__PURE__*/t(r.Fragment,{children:[/*#__PURE__*/e(\"h2\",{children:\"What are API Keys?\"}),/*#__PURE__*/e(\"p\",{children:\"API keys are security keys that guard your APIs allowing authenticated and authorized access. When building an API, you must offer keys to your users to allow them to connect to your APIs, otherwise your APIs will be public and accessible by everyone.\"}),/*#__PURE__*/e(\"h2\",{children:\"What do they do?\"}),/*#__PURE__*/t(\"ol\",{children:[/*#__PURE__*/e(\"li\",{\"data-preset-tag\":\"p\",children:/*#__PURE__*/e(\"p\",{children:\"Authenticate the underlying user\"})}),/*#__PURE__*/e(\"li\",{\"data-preset-tag\":\"p\",children:/*#__PURE__*/e(\"p\",{children:\"Grant permissions to limit access\"})}),/*#__PURE__*/e(\"li\",{\"data-preset-tag\":\"p\",children:/*#__PURE__*/e(\"p\",{children:\"Limit API usage to prevent abuse\"})}),/*#__PURE__*/e(\"li\",{\"data-preset-tag\":\"p\",children:/*#__PURE__*/e(\"p\",{children:\"Allows revocation in case it was leaked.\"})}),/*#__PURE__*/e(\"li\",{\"data-preset-tag\":\"p\",children:/*#__PURE__*/e(\"p\",{children:\"Allows generating usage analytics\"})}),/*#__PURE__*/e(\"li\",{\"data-preset-tag\":\"p\",children:/*#__PURE__*/e(\"p\",{children:\"Limit based on number of times used\"})}),/*#__PURE__*/e(\"li\",{\"data-preset-tag\":\"p\",children:/*#__PURE__*/e(\"p\",{children:\"IP restrictions\"})}),/*#__PURE__*/e(\"li\",{\"data-preset-tag\":\"p\",children:/*#__PURE__*/e(\"p\",{children:\"and more\"})})]}),/*#__PURE__*/e(\"h2\",{children:\"Implementation\"}),/*#__PURE__*/e(\"h5\",{children:\"Permissioning\"}),/*#__PURE__*/t(\"p\",{children:[\"Start by understanding and defining how you want to limit access to your system. In the following example, we create a scope called \",/*#__PURE__*/e(\"code\",{children:\"billing\"}),\" and allow full CRUD access to this scope.\"]}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'const billingScope = {\\n  representation: \"billing\",\\n  read: true,\\n  create: true,\\n  update: true,\\n  del: true\\n}',language:\"JSX\"})})}),/*#__PURE__*/t(\"p\",{children:[\"Next, we must attach this scope of the generated API key. Depending on your requirements you can make the scopes immutable or mutable. \",/*#__PURE__*/e(\"br\",{}),/*#__PURE__*/e(\"br\",{}),\"Now understand how this relates to your endpoints. For endpoints, that require \",/*#__PURE__*/e(\"code\",{children:\"create\"}),\" access to this scope, the middleware needs to check that the key has the required scope.\"]}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'function hasRequiredScope(\\n  scope: Scope,\\n  representation: string, \\n  create?: boolean, \\n  read?: boolean,\\n  update?: boolean,\\n  del?: boolean\\n): boolean {\\n  if (scope.representation !== representation) return false;\\n  if (create && scope.create !== create) return false;\\n  if (read && scope.read !== read) return false;\\n  if (update && scope.update !== update) return false;\\n  if (del && scope.del !== del) return false;\\n  return true;\\n}\\n\\nhasRequiredScope(billingScope, \"billing\", true, false, false, false);',language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:\"Now you must define all scopes that your system requires and then reference them in your middleware checks. \"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"strong\",{children:\"With Oneloop, you do need to write scopes and you do not need to verify scopes. Our SDKs and middleware takes care of it.\"})}),/*#__PURE__*/e(\"p\",{children:\"In the following image, we have defined two scopes with ease. We can add unlimited scopes as we desire.\"}),/*#__PURE__*/e(\"img\",{alt:\"\",className:\"framer-image\",\"data-framer-asset\":\"data:framer/asset-reference,GDWvxuB8wofl5DLDzvxmzEMO0.png\",\"data-framer-height\":\"1462\",\"data-framer-width\":\"2996\",height:\"731\",src:\"https://framerusercontent.com/images/GDWvxuB8wofl5DLDzvxmzEMO0.png\",srcSet:\"https://framerusercontent.com/images/GDWvxuB8wofl5DLDzvxmzEMO0.png?scale-down-to=512 512w,https://framerusercontent.com/images/GDWvxuB8wofl5DLDzvxmzEMO0.png?scale-down-to=1024 1024w,https://framerusercontent.com/images/GDWvxuB8wofl5DLDzvxmzEMO0.png?scale-down-to=2048 2048w,https://framerusercontent.com/images/GDWvxuB8wofl5DLDzvxmzEMO0.png 2996w\",style:{aspectRatio:\"2996 / 1462\"},width:\"1498\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h5\",{children:\"Rate Limiting\"}),/*#__PURE__*/e(\"p\",{children:\"For rate-limiting you can use the fixed window algorithm. The idea is that you use an unique id and time combination to understand how many requests are made. \"}),/*#__PURE__*/e(\"p\",{children:\"The hard part is the infrastructure needed and the guarantee of accuracy in a high-concurrency environment.\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'const keyId: string = \"sk_XCADFD\";\\nconst time: string = \"1724100985\";\\nconst window: string = 60; // seconds\\n\\nconst combinedKey = \"17241001020\"\\n\\n// TODO: Ensure atomicity and accuracy in a high-concurrency environment\\nif (count[combinedKey]) >= rateLimit) {\\n  // rate limit the request\\n}\\n\\ncount[combinedKey] += 1; // increment',language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h5\",{children:\"IP Restriction\"}),/*#__PURE__*/e(\"p\",{children:\"Limit access to API from white-listed customer systems for enhanced security. For even limit access to US IPs only and so on.\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h5\",{children:\"Usage Limits\"}),/*#__PURE__*/e(\"p\",{children:\"For trial tiers and certain billing tiers, you can limit access to your API for a limited number of times. The trick is to implement this with accuracy in a high-concurrency system where multiple requests are made at the system to different server.\"}),/*#__PURE__*/e(\"p\",{children:\"Here you can toggle the switch to turn on usage limit per API Key and set it to a valid number.\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"img\",{alt:\"\",className:\"framer-image\",\"data-framer-asset\":\"data:framer/asset-reference,iePmup0iqIHhhKx39O2Ekw2xHs0.png\",\"data-framer-height\":\"1108\",\"data-framer-width\":\"1008\",height:\"554\",src:\"https://framerusercontent.com/images/iePmup0iqIHhhKx39O2Ekw2xHs0.png\",srcSet:\"https://framerusercontent.com/images/iePmup0iqIHhhKx39O2Ekw2xHs0.png?scale-down-to=1024 931w,https://framerusercontent.com/images/iePmup0iqIHhhKx39O2Ekw2xHs0.png 1008w\",style:{aspectRatio:\"1008 / 1108\"},width:\"504\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h5\",{children:\"Usage Analytics\"}),/*#__PURE__*/e(\"p\",{children:\"Understanding how your systems are validating keys, total verifications, workspaces with the most keys and more. This gives you insight on customer behavior and confidence in your system.\"}),/*#__PURE__*/e(\"img\",{alt:\"\",className:\"framer-image\",\"data-framer-asset\":\"data:framer/asset-reference,omWpBdpRtw6dLkRuJrIq5rGLR4.png\",\"data-framer-height\":\"1450\",\"data-framer-width\":\"2986\",height:\"725\",src:\"https://framerusercontent.com/images/omWpBdpRtw6dLkRuJrIq5rGLR4.png\",srcSet:\"https://framerusercontent.com/images/omWpBdpRtw6dLkRuJrIq5rGLR4.png?scale-down-to=512 512w,https://framerusercontent.com/images/omWpBdpRtw6dLkRuJrIq5rGLR4.png?scale-down-to=1024 1024w,https://framerusercontent.com/images/omWpBdpRtw6dLkRuJrIq5rGLR4.png?scale-down-to=2048 2048w,https://framerusercontent.com/images/omWpBdpRtw6dLkRuJrIq5rGLR4.png 2986w\",style:{aspectRatio:\"2986 / 1450\"},width:\"1493\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h5\",{children:\"Language & SDK Support\"}),/*#__PURE__*/e(\"p\",{children:\"Depending on language and/or framework you use, having pre-written middleware make verifying keys breezy.\"}),/*#__PURE__*/e(\"img\",{alt:\"\",className:\"framer-image\",\"data-framer-asset\":\"data:framer/asset-reference,5Rppj64g8upfJqsmmSzBZBCW4Y.png\",\"data-framer-height\":\"1442\",\"data-framer-width\":\"2560\",height:\"721\",src:\"https://framerusercontent.com/images/5Rppj64g8upfJqsmmSzBZBCW4Y.png\",srcSet:\"https://framerusercontent.com/images/5Rppj64g8upfJqsmmSzBZBCW4Y.png?scale-down-to=512 512w,https://framerusercontent.com/images/5Rppj64g8upfJqsmmSzBZBCW4Y.png?scale-down-to=1024 1024w,https://framerusercontent.com/images/5Rppj64g8upfJqsmmSzBZBCW4Y.png?scale-down-to=2048 2048w,https://framerusercontent.com/images/5Rppj64g8upfJqsmmSzBZBCW4Y.png 2560w\",style:{aspectRatio:\"2560 / 1442\"},width:\"1280\"}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h5\",{children:\"UI\"}),/*#__PURE__*/e(\"p\",{children:\"If your API keys are accessible to your users on your dashboard, then you need to implement the necessary UI. This UI will let your customers issue, revoke, rotate, enable, delete keys with ease. Your UI will also ensure that in a multi-tenant environment the right keys are loaded.\"}),/*#__PURE__*/e(\"p\",{children:\"At Oneloop, we have built React embeddable components that you can show to your users with a single line of code, allowing your users to do everything.\"}),/*#__PURE__*/e(\"img\",{alt:\"\",className:\"framer-image\",\"data-framer-asset\":\"data:framer/asset-reference,aUsynJqdVEeN1unx9rwtuvJvsY.png\",\"data-framer-height\":\"1014\",\"data-framer-width\":\"1690\",height:\"507\",src:\"https://framerusercontent.com/images/aUsynJqdVEeN1unx9rwtuvJvsY.png\",srcSet:\"https://framerusercontent.com/images/aUsynJqdVEeN1unx9rwtuvJvsY.png?scale-down-to=512 512w,https://framerusercontent.com/images/aUsynJqdVEeN1unx9rwtuvJvsY.png?scale-down-to=1024 1024w,https://framerusercontent.com/images/aUsynJqdVEeN1unx9rwtuvJvsY.png 1690w\",style:{aspectRatio:\"1690 / 1014\"},width:\"845\"}),/*#__PURE__*/e(\"h2\",{children:\"Conclusion\"}),/*#__PURE__*/e(\"p\",{children:\"As you can see there is a lot that goes in building a secure, scalable and speedy API key system.\"}),/*#__PURE__*/t(\"p\",{children:[\"Every company building an API ends up building all these components in-house spending weeks initially and then time on future maintenance and feature-building work. But instead companies should focus on reducing time-to-market, and not building an MVP API Key infrastructure when Oneloop exists.\",/*#__PURE__*/e(\"br\",{}),/*#__PURE__*/e(\"br\",{}),\"Sign up \",/*#__PURE__*/e(n,{href:\"https://dashboard.oneloop.ai\",openInNewTab:!0,smoothScroll:!1,children:/*#__PURE__*/e(\"a\",{children:\"here\"})}),\", or schedule a call with me \",/*#__PURE__*/e(n,{href:\"https://calendar.app.google/iJKLvHwsotyziCGNA\",openInNewTab:!0,smoothScroll:!1,children:/*#__PURE__*/e(\"a\",{children:\"here\"})}),\" if you want to get done with keys in 5 mins.\"]})]});export const richText9=/*#__PURE__*/t(r.Fragment,{children:[/*#__PURE__*/e(\"h1\",{children:/*#__PURE__*/e(\"strong\",{children:\"API Authentication for Modern Web Apps\"})}),/*#__PURE__*/e(\"p\",{children:\"Companies like Clay, which specializes in sales automation, and Sardine, a player in the fintech space, are prime examples of businesses that build their entire services on top of APIs. As these companies demonstrate, APIs are not just a convenience; they are the backbone of modern web applications, enabling seamless integration, data exchange, and functionality across platforms. However, with this API-centric architecture comes the critical responsibility of ensuring that only authorized users and systems can access these APIs. This is where API authentication comes into play, and one effective method for securing APIs is through the use of API keys.\"}),/*#__PURE__*/e(\"p\",{children:\"In this article, we'll explore why API authentication is vital for modern web applications and provide practical TypeScript examples on how to generate, store, and validate API keys.\"}),/*#__PURE__*/e(\"h3\",{children:\"What is an API Key?\"}),/*#__PURE__*/e(\"p\",{children:\"An API key is a unique identifier passed along with API requests, used to authenticate the client making the request. API keys are typically strings of alphanumeric characters and are crucial for controlling access to your API, monitoring usage, and ensuring security.\"}),/*#__PURE__*/e(\"h3\",{children:\"Why API Keys Matter\"}),/*#__PURE__*/t(\"p\",{children:[\"1. \",/*#__PURE__*/e(\"strong\",{children:\"Security\"}),\": API keys help prevent unauthorized access to your APIs.\"]}),/*#__PURE__*/t(\"p\",{children:[\"2. \",/*#__PURE__*/e(\"strong\",{children:\"Access Control\"}),\": You can control which clients have access to specific APIs.\"]}),/*#__PURE__*/t(\"p\",{children:[\"3. \",/*#__PURE__*/e(\"strong\",{children:\"Monitoring and Analytics\"}),\": API keys can track usage and monitor how clients interact with your API.\"]}),/*#__PURE__*/e(\"h3\",{children:\"Step 1: Generating API Keys\"}),/*#__PURE__*/e(\"p\",{children:\"Let\u2019s start by generating an API key using TypeScript. Here\u2019s how you can use the `crypto` module from Node.js to generate a secure, random API key.\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:\"import crypto from 'crypto';\\nfunction generateApiKey(): string {\\n    return crypto.randomBytes(32).toString('hex');\\n}\\nconst apiKey = generateApiKey();\\nconsole.log(`Generated API Key: ${apiKey}`);\",language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:\"This function generates 32 bytes of random data and converts it to a hexadecimal string, producing a 64-character long API key.\"}),/*#__PURE__*/e(\"h3\",{children:\"Step 2: Storing API Keys\"}),/*#__PURE__*/e(\"p\",{children:\"After generating an API key, it needs to be stored securely. In a real-world scenario, this would involve storing the key in a database like MongoDB, PostgreSQL, or MySQL. For simplicity, here\u2019s an example using an in-memory object:\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:\"interface ApiKeyRecord {\\n    key: string;\\n    createdAt: Date;\\n    isActive: boolean;\\n}\\n\\nconst apiKeyStore: Record<string, ApiKeyRecord> = {};\\n\\nfunction storeApiKey(key: string) {\\n    const record: ApiKeyRecord = {\\n        key,\\n        createdAt: new Date(),\\n        isActive: true,\\n    };\\n    apiKeyStore[key] = record;\\n    console.log(`API Key stored: ${key}`);\\n}\\n\\nstoreApiKey(apiKey);\",language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:\"This example uses an object as a mock database, associating each API key with metadata such as creation date and active status.\"}),/*#__PURE__*/e(\"h3\",{children:\"Step 3: Validating API Keys\"}),/*#__PURE__*/e(\"p\",{children:\"To ensure that only authorized clients can access your API, you\u2019ll need to validate the provided API key.\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:\"function validateApiKey(key: string): boolean {\\n    const record = apiKeyStore[key];\\n    if (record && record.isActive) {\\n        console.log(`API Key valid: ${key}`);\\n        return true;\\n    } else {\\n        console.log(`API Key invalid: ${key}`);\\n        return false;\\n    }\\n}\\n\\nconst isValid = validateApiKey(apiKey); // This should return true\",language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:\"This function checks if the API key exists and is active. If both conditions are met, the key is considered valid.\"}),/*#__PURE__*/e(\"h3\",{children:\"Step 4: Using API Keys in Your API\"}),/*#__PURE__*/e(\"p\",{children:\"Here\u2019s how you can integrate API key authentication into an Express server using TypeScript:\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:\"import express, { Request, Response, NextFunction } from 'express';\\nconst app = express();\\nconst PORT = 3000;\\n\\n// Middleware to check API key\\nfunction apiKeyMiddleware(req: Request, res: Response, next: NextFunction) {\\n    const apiKey = req.header('x-api-key');\\n    if (apiKey && validateApiKey(apiKey)) {\\n        next();\\n    } else {\\n        res.status(401).json({ error: 'Unauthorized' });\\n    }\\n}\\n\\n// Protected route\\napp.get('/protected', apiKeyMiddleware, (req: Request, res: Response) => {\\n    res.json({ message: 'You have accessed a protected route!' });\\n});\\n\\napp.listen(PORT, () => {\\n    console.log(`Server is running on http://localhost:${PORT}`);\\n});\",language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:\"This example includes a middleware function that checks for an API key in the request headers. If the key is valid, the request is allowed to proceed to the protected route; otherwise, a 401 Unauthorized response is returned.\"}),/*#__PURE__*/e(\"h3\",{children:\"Scaling for Production\"}),/*#__PURE__*/e(\"p\",{children:\"While the above examples provide a basic implementation, more work is required to make this system production-ready:\"}),/*#__PURE__*/t(\"p\",{children:[\"1. \",/*#__PURE__*/e(\"strong\",{children:\"Scopes and Permissions\"}),\": In a production environment, API keys should include scopes or permissions that limit what the key can access. This allows for fine-grained control over what each API key can do.\"]}),/*#__PURE__*/t(\"p\",{children:[\"2. \",/*#__PURE__*/e(\"strong\",{children:\"Expiration and Rotation\"}),\": API keys should have an expiration date to reduce the risk of misuse over time. Additionally, you should implement key rotation mechanisms to regularly update keys without disrupting service.\"]}),/*#__PURE__*/t(\"p\",{children:[\"3. \",/*#__PURE__*/e(\"strong\",{children:\"Storing API Keys Securely\"}),\": API keys should be stored securely, often hashed, in a database rather than in plain text. This prevents attackers from easily accessing them in case of a data breach.\"]}),/*#__PURE__*/t(\"p\",{children:[\"4. \",/*#__PURE__*/e(\"strong\",{children:\"High-Performance Verification\"}),\": In a production environment, verifying API keys at scale requires efficient lookups. This can be achieved using a combination of database indexing and caching strategies, such as Redis, to reduce the load on your primary database.\"]}),/*#__PURE__*/t(\"p\",{children:[\"5. \",/*#__PURE__*/e(\"strong\",{children:\"Rate Limiting and Monitoring\"}),\": Implementing rate limiting based on API keys can help prevent abuse and ensure fair usage of your API. Additionally, monitoring and logging API key usage is essential for detecting and responding to potential security threats.\"]}),/*#__PURE__*/e(\"h3\",{children:\"Conclusion\"}),/*#__PURE__*/e(\"p\",{children:\"API authentication is essential for securing modern web applications, especially for companies like Clay and Sardine that rely heavily on APIs for their core business functions. While the basic examples provided here offer a starting point for generating, storing, and validating API keys in TypeScript, making this system production-ready requires additional considerations like scopes, expiration, secure storage, and scaling verification mechanisms. By implementing these best practices, you can ensure that your APIs remain secure, performant, and scalable as your application grows.\"})]});export const richText10=/*#__PURE__*/t(r.Fragment,{children:[/*#__PURE__*/e(\"p\",{children:\"Today we are going to explore how to add authentication to your public API endpoints built on NextJs\"}),/*#__PURE__*/e(\"h2\",{children:\"Background\"}),/*#__PURE__*/e(\"p\",{children:\"NextJS has gained huge popularity over the past few years. It's features like Server Side Rendering (SSR), Static Site Generation, and built-in API support offer improved performance, advanced SEO optimization, and a great developer experience. With NextJS, you can define your frontend and backend code in a single repository.\"}),/*#__PURE__*/e(\"p\",{children:\"Using Oneloop, you can quickly and easily add API keys to your NextJS routes. It's like Auth0, but for your API\"}),/*#__PURE__*/e(\"h2\",{children:\"Getting Started with NextJS App\"}),/*#__PURE__*/t(\"p\",{children:[\"The easiest way to get started is to using \",/*#__PURE__*/e(\"code\",{children:\"create-next-app\"}),\". More info \",/*#__PURE__*/e(n,{href:\"https://nextjs.org/docs/getting-started/installation\",openInNewTab:!0,smoothScroll:!1,children:/*#__PURE__*/e(\"a\",{children:\"here\"})})]}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:\"npx create-next-app@latest\",language:\"JSX\"})})}),/*#__PURE__*/e(\"h2\",{children:\"Install Oneloop NextJS SDK\"}),/*#__PURE__*/e(\"p\",{children:\"Now we will install Oneloop NextJS SDK. This SDK wraps your functions and takes care of all the middleware and error handling. With this, you will be able to convert any of your endpoint route to an authenticated route, with a single line change\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:\"npm install @oneloop-hq/next@latest\",language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h2\",{children:\"Adding API to your NextJS App\"}),/*#__PURE__*/t(\"p\",{children:[\"Once you are in your NextJS app, go to \",/*#__PURE__*/e(\"code\",{children:\"app/api\"}),\" folder and create 2 new directories \",/*#__PURE__*/e(\"code\",{children:\"/health\"}),\" and \",/*#__PURE__*/e(\"code\",{children:\"/profile\"}),\". Each of there directories represents a valid endpoint. Now let's create \",/*#__PURE__*/e(\"code\",{children:\"route.js|ts\"}),\" under each of these new directories. These route files will contain our \",/*#__PURE__*/e(\"code\",{children:\"GET|POST|PATCH|DEL\"}),\" calls. Learn more about \",/*#__PURE__*/e(n,{href:\"https://nextjs.org/docs/app/building-your-application/routing/route-handlers\",openInNewTab:!0,smoothScroll:!1,children:/*#__PURE__*/e(\"a\",{children:\"Route Handlers with NextJS\"})})]}),/*#__PURE__*/e(\"h3\",{children:\"Add unauthenticated endpoint\"}),/*#__PURE__*/t(\"p\",{children:[\"Let us first start by testing our endpoints and make sure we can hit them successfully. Go to \",/*#__PURE__*/e(\"code\",{children:\"app/api/health/route.ts\"}),\" and add the following code\"]}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'export const dynamic = \"force-dynamic\"; // defaults to auto\\nexport async function GET(request: Request) {\\n  return new Response(\"Hello from the API\", {\\n    headers: {\\n      \"content-type\": \"text/plain\",\\n    },\\n  });\\n}',language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/t(\"p\",{children:[\"Let's test this endpoint now by first running our app using \",/*#__PURE__*/e(\"code\",{children:\"npm run dev\"}),\" and then hitting this endpoint in our terminal\"]}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:\"curl http://localhost:3000/api/health\",language:\"JSX\"})})}),/*#__PURE__*/t(\"p\",{children:[\"This should give back a 200 with text \",/*#__PURE__*/e(\"code\",{children:\"Hello from the API\"})]}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h3\",{children:\"Add authenticated endpoint\"}),/*#__PURE__*/t(\"p\",{children:[\"Now let's do the same for our profile endpoint, but this time we will add authentication to it using Oneloop. The first step will be to signup for \",/*#__PURE__*/e(n,{href:\"https://dashboard.onelooop.ai/\",openInNewTab:!0,smoothScroll:!1,children:/*#__PURE__*/e(\"a\",{children:\"Oneloop account\"})}),\" and generate your own SDK Keys. Learn more \",/*#__PURE__*/e(n,{href:\"https://docs.oneloop.ai/documentation/quickstart\",openInNewTab:!0,smoothScroll:!1,children:/*#__PURE__*/e(\"a\",{children:\"here\"})})]}),/*#__PURE__*/e(\"p\",{children:\"Once you have your Oneloop SDK Keys, let's add the code for our endpoint along with authentication\"}),/*#__PURE__*/e(\"blockquote\",{children:/*#__PURE__*/t(\"p\",{children:[\"\u26A0Remember to replace \",/*#__PURE__*/e(\"code\",{children:\"YOUR_ONELOOP_SDK_KEY\"}),\" with your Oneloop SDK Key\"]})}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'import { useOneloop } from \"@oneloop-hq/nextjs\";\\n\\nexport const dynamic = \"force-dynamic\"; // defaults to auto\\n\\n// eslint-disable-next-line\\nexport const GET = useOneloop(\\n  async (request: Request) => {\\n    return new Response(\"Profile Endpoint Authenticated\", {\\n      headers: {\\n        \"content-type\": \"text/plain\",\\n      },\\n    });\\n  },\\n  {sdkKey: \"YOUR_ONELOOP_SDK_KEY\"}\\n);',language:\"JSX\"})})}),/*#__PURE__*/e(\"p\",{children:/*#__PURE__*/e(\"br\",{className:\"trailing-break\"})}),/*#__PURE__*/e(\"h2\",{children:\"Testing our authenticated endpoint\"}),/*#__PURE__*/e(\"p\",{children:\"Now let's first start by testing our endpoint without giving any authorization header\"}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:\"curl http://localhost:3000/api/profile\",language:\"JSX\"})})}),/*#__PURE__*/t(\"p\",{children:[\"This should give you a 401 error saying \",/*#__PURE__*/e(\"code\",{children:'{\"error\":\"unauthorized\"}'})]}),/*#__PURE__*/t(\"p\",{children:[\"Now let's add our API Key and authenticate this endpoint. To generate an API Key, you can either use \",/*#__PURE__*/e(n,{href:\"https://dashboard.oneloop.ai/api-keys-manager\",openInNewTab:!0,smoothScroll:!1,children:/*#__PURE__*/e(\"a\",{children:\"Oneloop Dashboard\"})}),\" or use the following command below to get an API Key\"]}),/*#__PURE__*/e(\"blockquote\",{children:/*#__PURE__*/t(\"p\",{children:[\"\uD83D\uDCA1Remember to replace YOUR_WORKSPACE_ID with your Oneloop Workspace ID. You can get this from your \",/*#__PURE__*/e(n,{href:\"https://dashboard.oneloop.ai/workspace-settings\",openInNewTab:!0,smoothScroll:!1,children:/*#__PURE__*/e(\"a\",{children:\"Oneloop Dashboard\"})})]})}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:'curl -H \\'Content-Type: application/json\\' \\\\ -d \\'{ \"name\":\"Test Key\",\"workspaceId\":\"YOUR_WORKSPACE_ID\", \"customerID\": \"Test-Customer-ID\", \"scopes\": [], \"enabled\": true }\\' \\\\ -X POST \\\\ https://api.oneloop.ai/v1/api-key',language:\"JSX\"})})}),/*#__PURE__*/t(\"p\",{children:[\"Now using the newly generated API Key, let's test our authenticated \",/*#__PURE__*/e(\"code\",{children:\"/profile\"}),\" endpoint again\"]}),/*#__PURE__*/e(a.div,{className:\"framer-text-module\",style:{height:\"auto\",width:\"100%\"},children:/*#__PURE__*/e(i,{componentIdentifier:\"module:pVk4QsoHxASnVtUBp6jr/TbhpORLndv1iOkZzyo83/CodeBlock.js:default\",children:t=>/*#__PURE__*/e(o,{...t,code:\"curl -H 'Authorization: YOUR_API_KEY' \\\\ https://api.oneloop.ai/v1/api-key\",language:\"JSX\"})})}),/*#__PURE__*/t(\"p\",{children:[\"This should give you a 200 response saying \",/*#__PURE__*/e(\"code\",{children:\"Profile Endpoint Authenticated\"})]}),/*#__PURE__*/e(\"h2\",{children:\"Recap\"}),/*#__PURE__*/t(\"p\",{children:[\"So we just saw how we can add authenticated routes to our NextJS app with a few lines of code. You can get this entire code from our GitHub repository. There are more features that you get with \",/*#__PURE__*/e(n,{href:{webPageId:\"augiA20Il\"},openInNewTab:!1,smoothScroll:!1,children:/*#__PURE__*/e(\"a\",{children:\"Oneloop\"})}),\", like rate limiting, usage tracking, audit logs, and ip restrictions. But that is for another article\"]}),/*#__PURE__*/e(\"p\",{children:\"Happy building!\"})]});\nexport const __FramerMetadata__ = {\"exports\":{\"richText5\":{\"type\":\"variable\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"richText1\":{\"type\":\"variable\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"richText6\":{\"type\":\"variable\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"richText8\":{\"type\":\"variable\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"richText7\":{\"type\":\"variable\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"richText9\":{\"type\":\"variable\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"richText2\":{\"type\":\"variable\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"richText4\":{\"type\":\"variable\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"richText\":{\"type\":\"variable\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"richText3\":{\"type\":\"variable\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"richText10\":{\"type\":\"variable\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}"],
  "mappings": "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",
  "names": ["richText", "u", "x", "p", "motion", "ComponentPresetsConsumer", "t", "CodeBlock_default", "richText1", "richText2", "richText3", "richText4", "richText5", "richText6", "Link", "richText7", "richText8", "richText9", "richText10", "__FramerMetadata__"]
}
