Connecting Spring Boot Applications to LinkedIn for Profile Retrieval

Australian recruitment platforms and professional networking tools increasingly rely on verified career data, and pulling that information directly from LinkedIn through a Spring Boot backend has become a common requirement for HR tech vendors in Sydney and Melbourne. Whether you are building a candidate-matching engine for a Brisbane-based startup or an enterprise onboarding portal for a Perth mining company, the integration pathway follows predictable patterns once you understand the underlying OAuth 2.0 flow.

This walkthrough covers registering an application, configuring Spring Security for delegated authentication, building a resilient REST client, and mapping the resulting JSON payload into typed Java records. You will also see how to respect the Australian Privacy Principles while storing tokens and profile attributes, a detail that matters more than ever given the stricter expectations from local regulators.

Registering Your Application on the LinkedIn Developer Portal

Begin by creating an application inside the LinkedIn Developer Portal. Choose "Sign In with LinkedIn using OpenID Connect" rather than the older v1 API, because the v2 endpoints return cleaner profile fields and are the path LinkedIn actively maintains. Supply a redirect URI that matches your local environment, such as http://localhost:8080/login/oauth2/code/linkedin during development, and add your production callback URL once you deploy to a server hosted in an Australian region like AWS Sydney (ap-southeast-2).

Note down the Client ID and Client Secret, then request the scopes your application actually needs. Requesting excessive permissions delays the review process and can lead to rejection, particularly if your use case is not clearly B2B-focused. Store these credentials outside your source tree using environment variables or a secrets manager such as HashiCorp Vault, since committing them to a public GitHub repository will get the application suspended quickly.

Typical scopes for profile retrieval:

Wiring Spring Security for the Authorization Code Flow

Spring Boot 3.x ships with first-class OAuth2 client support, so the configuration is largely declarative. Add spring-boot-starter-oauth2-client to your Maven or Gradle build, then register LinkedIn as a provider inside application.yml. LinkedIn uses a non-standard issuer URI, so you will need to override the user info endpoint manually rather than relying on the default OpenID discovery document.

Once authenticated, Spring Security stores the access token in the principal, making it available to downstream services through OAuth2AuthenticationToken. Australian teams often layer additional checks here, validating that the returned email domain matches the expected corporate domain when the integration supports single-tenant deployments for clients such as the big-four banks headquartered in Sydney's CBD.

Building a Dedicated Profile Client Service

Rather than scattering HTTP calls across controllers, encapsulate LinkedIn interactions inside a dedicated @Service class. Inject RestClient or WebClient depending on whether you prefer blocking or reactive flows, and configure it with a sensible timeout. LinkedIn's profile endpoint is https://api.linkedin.com/v2/userinfo, which returns the OpenID-compliant payload including given name, family name, picture URL, and locale.

A practical approach is to wrap the call in a method that accepts an OAuth2AuthenticationToken and returns a domain object. This keeps controllers thin and makes unit testing straightforward using Mockito to stub the client. Many Brisbane and Adelaide developers also add caching with Caffeine or Redis, because LinkedIn rate limits anonymous bursts aggressively and a recruitment portal can easily burn through quota during peak application periods around EOFY hiring drives.

Mapping the JSON Response to Typed Records

Java 17 records pair beautifully with the flat structure returned by LinkedIn's user info endpoint. Define a record such as LinkedInProfile(String sub, String givenName, String familyName, String email, String picture, String locale) and let Jackson populate it directly. Add @JsonIgnoreProperties(ignoreUnknown = true) so future schema additions from LinkedIn do not break your build overnight.

If your domain model requires nested structures, consider using @JsonProperty annotations to map snake_case fields like family_name onto camelCase Java fields. Australian teams building bilingual portals for Mandarin-speaking clients in Chatswood or Hurstville often extend this record with additional fields, capturing both the English and localised display names that LinkedIn occasionally provides for international members.

Handling Errors, Retries, and Quota Exhaustion

Treat LinkedIn as an external dependency with the same care you would give to Stripe or Atlassian. Wrap calls in try-catch blocks that distinguish between 401 (refresh the token), 403 (re-prompt the user), 429 (back off using exponential delay), and 500 (retry with jitter). The Resilience4j library integrates cleanly with Spring Boot through its actuator starter and provides circuit breakers that prevent cascading failures when LinkedIn experiences an outage, as happened during the 2023 regional disruptions that affected several SaaS providers across Asia-Pacific.

Log correlation IDs alongside the LinkedIn member identifier so support teams can trace issues without exposing personally identifiable information. Avoid logging the raw access token, and redact the sub field in production logs unless you have explicit consent, since Australia's Notifiable Data Breaches scheme carries serious penalties for unintended disclosures.

Resilience patterns worth adopting:

Storing Tokens and Respecting Local Privacy Norms

Persist refresh tokens encrypted at rest using a library such as spring-security-crypto backed by an AWS KMS key stored in the Sydney region. Never store profile attributes longer than your stated retention policy allows, and expose a self-service deletion endpoint that purges both the database row and any cached entries in Redis. Australian users increasingly expect this level of control, and embedding it from day one saves costly refactors later.

Document the data flow in a privacy policy that aligns with the Australian Privacy Principles. Mention which fields you collect, how long you retain them, and how users can request removal. Doing so builds trust with candidates who interact with platforms built by your team, whether you operate out of a coworking space in Surry Hills or a corporate office in Docklands.