Mastering Consuming Liferay Headless APIs

Consuming Liferay APIs in Frontend Contexts

Modern digital experiences rely on effective user interfaces and visual customization. Liferay's headless APIs provide the flexibility to power these experiences, enabling you to present information dynamically within both Liferay pages and external frontends. Delivering these rich experiences means consuming API data securely, filtering it precisely, and ensuring it's served efficiently.

In this lesson, you'll explore practical methods for consuming Liferay APIs within various frontend contexts.

Understanding API Call Approaches

Whether you're rendering Liferay fragments, displaying frontend client extensions, or building external applications, Liferay's headless APIs provide the data needed for flexible, dynamic UIs. These frontend API calls generally follow one of two patterns based on their origin:

  • Client-to-Server: Made directly from the user's browser (e.g., via JavaScript). This is typical for client extensions and direct calls from fragments.
  • Server-to-Server: Made from a server environment (e.g., using restClient in a Liferay fragment).

Client-to-server calls are common for browser-based logic (such as client extensions and dynamic dashboards with fragments), while server-to-server calls often happen during server-side rendering (static dashboards with fragments) or via intermediary backends. You'll explore the advantages of these call methods in Comparing Frontend API Approaches.

Consuming APIs Within Liferay Pages

Liferay pages assemble fragments, widgets, and frontend client extensions to build versatile user experiences. To create dynamic pages, these components often call Liferay APIs to retrieve data or execute operations.

Securing these API calls within a Liferay page context is critical. You'll primarily leverage Cross-Site Request Forgery (CSRF) tokens for session-based requests and OAuth 2.0 for delegated authorization scenarios. You'll now explore how to handle API consumption and authentication within specific components like fragments and client extensions.

NOTE
CSRF tokens are unique, secret, and unpredictable values to generated by Liferay to block CSRF attacks and provided to the client (e.g., via Liferay.authToken in JavaScript). By requiring this token on state-changing requests, Liferay ensures actions are initiated intentionally from its own interface, not maliciously triggered by another website abusing the user's active session.

Consuming APIs from Fragments

Liferay fragments provide versatility, enabling both client-to-server and server-to-server calls with Liferay's headless APIs. How authentication is managed depends on the approach:

  • For client-to-server requests such as JavaScript (AJAX) calls, the browser includes the session's JSESSIONID information, and a x-csrf-token is available via Liferay.authToken.
  • For server-to-server restClient calls, you don't need to include authentication headers manually as everything is included within the server context.

This server-side execution capability combined with access to the user's session context (both client-side and server-side) simplifies authenticating API calls from fragments compared to completely external applications.

Consuming APIs from Frontend Client Extensions

Frontend client extensions, particularly custom elements, offer a powerful way to extend Liferay by creating independent micro-frontends. These components fetch and display data securely using Liferay's headless APIs, running directly within the user's browser on a Liferay page.

Since they operate within the authenticated user's session context (client-side), API calls made from these extensions automatically include the browser's session-based authentication and CSRF token protection, much like fragments.

However, unlike fragments, frontend client extensions function outside Liferay's server environment. This external execution directly impacts API calls, as restClient is not accessible. Calls must be made with a client-to-server approach relying on JavaScript or frameworks like React, Vue.js, or Angular.

When consuming APIs from frontend client extensions, consider these best practices:

  • Construct Base URLs Dynamically: Leverage window.location.origin to ensure API requests remain within the Liferay instance.
  • Include CSRF Tokens: Directly pass the CSRF token (x-csrf-token) to maintain security and prevent cross-site request forgery (CSRF) attacks.
  • Implement Robust Error Handling: Check API response statuses (e.g., differentiate between 2xx success codes and 4xx/5xx errors), handle network failures gracefully (e.g., using try...catch with async/await), and provide appropriate feedback to the user.
NOTE
For more information on frontend client extensions, see official documentation (Client Extension Reference) or refer to the Mastering Liferay Frontend Client Extensions course for a holistic overview.

Consuming Within External Applications

Many applications interact with Liferay's APIs from entirely separate environments, creating a multi-channel experience. Operating and rendering outside of Liferay, these headless frontends include a wide variety of contexts including

  • Single Page Applications (SPAs): Build dynamic web applications seamlessly interacting with Liferay APIs using common frameworks like React, Angular, or Vue.js.
  • Mobile Applications: Surface relevant information for users within lightweight, portable applications.
  • External Web Components and Widgets: Embed components in external websites pulling dynamic content from Liferay.
  • Smartwatch and Wearable Apps: Display notifications, track tasks, or retrieve small pieces of data.
  • Smart TV Apps and Digital Signage: Stream enterprise dashboards or display content powered by Liferay.
  • IoT Devices and Appliances: Retrieve or send data to devices, including monitoring logs and smart device commands.
  • Kiosks and POS Systems: Integrate self-service kiosks or retail systems with Liferay for product details, orders, or customer profiles.
  • Voice Assistants and Chatbots: Query Liferay for support tickets, FAQs, or personalized recommendations.
  • AR/VR Applications: Display real-time data, product information, or training content using Liferay APIs.

While capabilities differ between these platforms, each requires efficient API interactions and explicit OAuth 2.0 authentication to integrate with Liferay. Once secured, these platforms can interact with Liferay's robust headless APIs to retrieve and manipulate data. This approach empowers creating highly integrated and scalable applications extending Liferay's capabilities beyond its native UI.

Exploring Clarity's Frontend API Implementations

For their evolving Liferay setup, Clarity will handle frontend API calls with a mix of fragments, client extensions, and external integrations. The following examples demonstrate how they can practice making these calls within varying contexts:

Fragments

Within fragments, Clarity can leverage both client-to-server and server-to-server calls. Clarity's environment includes a Tickets object containing individual ticket object entries. To fetch tickets with JavaScript with a client-to-server call, their fragment contains this structure:

const response = await fetch('/o/c/tickets', {
	method: 'GET',
	headers: {
		'Accept': 'application/json',
		'Content-Type': 'application/json',
		'x-csrf-token': Liferay.authToken
	}
});

Alternately, their approach to displaying tickets as part of a static dashboard can leverage with restClient with this server-to-server call:

[#assign tickets = restClient.get("/c/tickets") /]
[#if tickets?has_content]
	[#list tickets.items as ticket]
	<div class="ticket-row">
		<div class="ticket-column">${ticket.id}</div>
		<div class="ticket-column">${ticket.subject}</div>
		<div class="ticket-column">${ticket.creator.name}</div>
		<div class="ticket-column">${ticket.ticketStatus.name}</div>
	</div>
	[/#list]
[/#if]

Client Extensions

To retrieve Clarity's ticketing data within a custom element client extension, they'll call Liferay's headless APIs with this approach:

const fetchTickets = async () => {
    try {
           const response = await fetch('/o/c/tickets', {
            headers: {
              'Accept': 'application/json',
              'Content-Type': 'application/json',
              'x-csrf-token': Liferay.authToken
            }
      });
        if (!response.ok) {
            throw new Error(`Error fetching tickets: ${response.statusText}`);
        }
        const data = await response.json();
        return data.items;
    } catch (error) {
        console.error(error);
        return [];
    }
};

External to Liferay

For an external SPA, Clarity redirects users to Liferay's OAuth 2.0 authorization endpoint to obtain an access token. Once authenticated with the authorization code flow, API calls like the following can be made:

// Redirect the user to Liferay's OAuth endpoint
const clientId = "your-client-id";
const redirectUri = "https://your-spa.com/callback";
const authUrl = `https://liferay-instance/o/oauth2/authorize?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}`;
window.location.href = authUrl;
// Later, use the received access token to fetch data
const fetchTickets = async (accessToken) => {
	const response = await fetch("https://liferay-instance/o/c/tickets", {
	method: "GET",
	headers: {
		"Accept": "application/json",
		"Content-Type": "application/json",
		"Authorization": `Bearer ${accessToken}`
	}
	});
	return response.json();
};

For a mobile app, Clarity will follow a similar pattern to secure access Liferay APIs. But instead of the previous example's flow, they'll additionally leverage the Proof Key for Code Exchange (PKCE) flow:

import { generateCodeVerifier, generateCodeChallenge } from "pkce-challenge";
const { codeVerifier, codeChallenge } = generateCodeVerifier();
const clientId = "your-mobile-client-id";
const redirectUri = "your-mobile-app://callback";
const authUrl = `https://liferay-instance/o/oauth2/authorize?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}&code_challenge=${codeChallenge}&code_challenge_method=S256`;
window.location.href = authUrl;

Conclusion

Liferay's headless APIs empower developers to create dynamic user interfaces, whether enhancing Liferay pages with fragments and client extensions or building distinct headless frontends for multi-channel reach. Securely authenticating these API calls is paramount across all frontend contexts. Mastering API consumption allows developers to fully leverage Liferay's capabilities, delivering rich, visually engaging, and seamless digital solutions.

Next, you'll learn how to evaluate when each approach is appropriate for consuming APIs in frontend contexts.

  • Understanding API Call Approaches

  • Consuming APIs Within Liferay Pages

  • Consuming Within External Applications

  • Exploring Clarity's Frontend API Implementations

  • Conclusion

Loading Knowledge

Capabilities

Product

Education

Contact Us

Connect

Powered by Liferay
© 2024 Liferay Inc. All Rights Reserved • Privacy Policy