Building Custom AutoLogin Module for Liferay Integration with Azure AD B2C

Published: (March 31, 2026 at 12:36 PM EDT)
5 min read
Source: Dev.to

Source: Dev.to

Azure AD B2C + Liferay Integration

Azure AD B2C provides a robust, cloud‑based identity management solution that offers secure authentication, multi‑factor authentication support, and seamless integration with enterprise systems. When combined with Liferay’s flexible portal capabilities, you get a powerful platform that can handle complex authentication scenarios while maintaining a great user experience.


The Solution: Custom AutoLogin Module

The approach involves creating a custom AutoLogin component that intercepts the authentication flow, validates tokens from Azure B2C, and automatically logs users into Liferay.

Step 1 – Create the AutoLogin Class

Create a class that extends BaseAutoLogin. This class will handle the authentication logic:

public class WebsiteAutoLogin extends BaseAutoLogin {

    @Reference
    private UserLocalService userLocalService;

    private RestTemplate restTemplate;

    @Activate
    public void activateComponent() {
        restTemplate = new RestTemplate();
    }
}
  • @Reference injects Liferay’s UserLocalService, which we’ll use to look up users.
  • RestTemplate is initialized during component activation and will be used for HTTP calls to Azure B2C.

Step 2 – Implement the doLogin Method

The core authentication logic resides in the doLogin method:

public String[] doLogin(HttpServletRequest request,
                        HttpServletResponse response) throws AutoLoginException {

    // 1) Extract the ID token from the request
    String code = ParamUtil.getString(request, "id_token");

    // 2) Exchange code for ID token – call the B2C REST API
    String tokenEncodedString = retrieveAzureToken(code);

    // 3) Decode the JWT payload
    JSONObject payload = decodeJWTToken(tokenEncodedString);

    // 4) Extract user identifier from the token
    String screenName = payload.getString("MatchingScreenName");

    try {
        long companyId = PortalUtil.getCompanyId(request);

        // 5) Fetch existing user by screen name
        User user = userLocalService.fetchUserByScreenName(companyId, screenName);

        // 6) Return credentials for auto‑login
        return new String[] {
            String.valueOf(user.getUserId()),
            user.getPassword(),
            Boolean.TRUE.toString()
        };

    } catch (Exception e) {
        logger.error("Error during user login or creation: " + e.getMessage(), e);
        return null;
    }
}

What the method does

  1. Extracts the authorization code or ID token from the incoming request.
  2. Exchanges this code with Azure B2C to obtain a valid token.
  3. Decodes the JWT token to extract user information.
  4. Looks up the corresponding Liferay user.
  5. Returns the authentication credentials for automatic login.

Step 3 – Token Retrieval from Azure B2C

retrieveAzureToken handles communication with Azure B2C’s token endpoint:

private String retrieveAzureToken(String authorizationCode) {
    try {
        // Get the token endpoint URL
        String tokenEndpoint = getTokenEndpoint();

        // Create HTTP headers
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        // Encode the redirect URI
        String redirectUri = URLEncoder.encode("YOUR_REDIRECT_URL", "UTF-8");

        // Build form parameters
        MultiValueMap formParams = new LinkedMultiValueMap<>();
        formParams.add("client_id", B2C_AZURE_CLIENT_ID);
        formParams.add("client_secret", B2C_AZURE_CLIENT_SECRET);
        formParams.add("code", authorizationCode);
        formParams.add("grant_type", AUTH_GRANT_TYPE);
        formParams.add("redirect_uri", redirectUri);

        // Create and send the request
        HttpEntity> requestEntity =
            new HttpEntity<>(formParams, headers);

        ResponseEntity response = restTemplate.postForEntity(
            tokenEndpoint,
            requestEntity,
            String.class
        );

        // Parse and return the ID token
        JSONObject jsonObject = JSONFactoryUtil.createJSONObject(response.getBody());
        return jsonObject.getString("id_token");
    } catch (Exception e) {
        logger.error("Exception occurred on B2C Azure Token Request: " + e);
    }

    return null;
}

Step 4 – JWT Token Decoding

The JWT token returned by Azure B2C must be decoded to extract user claims:

public static JSONObject decodeJWTToken(String token) {
    try {
        if (Validator.isNull(token)) {
            return null;
        }

        // Split the token into header, payload, and signature
        String[] parts = token.split("\\.");

        // Decode the payload (second part) from Base64
        return JSONFactoryUtil.createJSONObject(decode(parts[1]));
    } catch (Exception e) {
        logger.error("Exception occurred while decoding the JSON token: " + e.getMessage());
    }

    return null;
}

Configuration Requirements

Azure AD B2C

  • Register your application in Azure AD B2C.
  • Configure the redirect URIs.
  • Note the Client ID and Client Secret.
  • Set up the appropriate user flows (sign‑in, sign‑up).

Liferay

  • Deploy the custom AutoLogin module.
  • Configure the module with your Azure B2C credentials (via Liferay’s secure configuration).
  • Ensure users exist in Liferay with matching screen names.

Security Considerations

When implementing this solution, keep these best practices in mind:

ConcernRecommendation
Credential storageStore Azure B2C client secrets in Liferay’s encrypted configuration (e.g., portal-ext.properties with portal.security.manager.enabled=true) – never hard‑code them.
Token validationVerify the JWT signature using Azure B2C’s public keys and check exp, nbf, and iss claims before trusting the token.
HTTPSAll communication with Azure B2C must occur over HTTPS.
Least‑privilegeGrant the Azure B2C app only the permissions it needs (e.g., openid, profile).
LoggingAvoid logging sensitive data such as tokens or passwords. Use masked logs if necessary.
Error handlingDo not expose stack traces to end‑users; log them securely and return generic error messages.

Following these guidelines will help you build a secure, maintainable integration between Azure AD B2C and Liferay.

usting its claims

  • HTTPS only: Ensure all communication happens over HTTPS.
  • Error handling: Implement proper error handling to avoid exposing sensitive information.
  • Logging: Log authentication events for auditing, but never log sensitive token data.

Conclusion

Integrating Azure AD B2C with Liferay through a custom AutoLogin module provides a secure and seamless authentication experience. This approach leverages Azure’s enterprise‑grade identity management while maintaining Liferay’s flexibility and extensibility.

The complete implementation gives you a foundation that can be extended to support additional features like user provisioning, role mapping based on Azure AD groups, and multi‑factor authentication.

0 views
Back to Blog

Related posts

Read more »

Global Variable VS Local Variable

Global Variable in Java Java does not support true global variables. Instead, it uses class‑level variables, which behave similarly. Types of Class‑Level Varia...