LinkedIn auth provider
The LinkedIn auth provider enables tools and agents to call the LinkedIn API on behalf of a user. Behind the scenes, the Arcade Engine and the LinkedIn auth provider seamlessly manage LinkedIn OAuth 2.0 authorization for your users.
What’s documented here
This page describes how to use and configure LinkedIn auth with Arcade.
This auth provider is used by:
- Your app code that needs to call LinkedIn APIs
- Or, your custom tools that need to call LinkedIn APIs
Configuring LinkedIn auth
In a production environment, you will most likely want to use your own LinkedIn app credentials. This way, your users will see your application’s name requesting permission.
You can use your own LinkedIn credentials in both the Arcade Cloud and in a self-hosted Arcade Engine instance.
Before showing how to configure your LinkedIn app credentials, let’s go through the steps to create a LinkedIn app.
Create a LinkedIn app
- Follow LinkedIn’s guide to setting up user authorization
- On the Products tab, add the products you need for your app (e.g. “Share on LinkedIn”)
- At a minimum, you must add the “Sign In with LinkedIn using OpenID Connect” product
- On the Auth tab, set the redirect URL to:
https://cloud.arcade.dev/api/v1/oauth/callback
- Copy the client ID and client secret to use below
Next, add the LinkedIn app to your Arcade Engine configuration. You can do this in the Arcade Dashboard, or by editing the engine.yaml
file directly (for a self-hosted instance).
Configuring your own LinkedIn Auth Provider in Arcade
There are two ways to configure your LinkedIn app credentials in Arcade:
- From the Arcade Dashboard GUI
- By editing the
engine.yaml
file directly (for a self-hosted Arcade Engine)
We show both options step-by-step below.
Configure LinkedIn Auth Using the Arcade Dashboard GUI
Access the Arcade Dashboard
To access the Arcade Cloud dashboard, go to api.arcade.dev/dashboard. If you are self-hosting, by default the dashboard will be available at http://localhost:9099/dashboard
. Adjust the host and port number to match your environment.
Navigate to the OAuth Providers page
- Under the OAuth section of the Arcade Dashboard left-side menu, click Providers.
- Click Add OAuth Provider in the top right corner.
- Select the Included Providers tab at the top.
- In the Provider dropdown, select LinkedIn.
Enter the provider details
- Choose a unique ID for your provider (e.g. “my-linkedin-provider”).
- Optionally enter a Description.
- Enter the Client ID and Client Secret from your LinkedIn app.
Create the provider
Hit the Create button and the provider will be ready to be used in the Arcade Engine.
When you use tools that require LinkedIn auth using your Arcade account credentials, the Arcade Engine will automatically use this LinkedIn OAuth provider. If you have multiple LinkedIn providers, see using multiple auth providers of the same type for more information.
Using LinkedIn auth in app code
Use the LinkedIn auth provider in your own agents and AI apps to get a user token for LinkedIn APIs. See authorizing agents with Arcade to understand how this works.
Use client.auth.start()
to get a user token for LinkedIn APIs:
import requests
from arcadepy import Arcade
client = Arcade() # Automatically finds the `ARCADE_API_KEY` env variable
user_id = "user@example.com"
"""
In this example, we will use Arcade to authenticate with LinkedIn and post a
message to the user's LinkedIn feed.
There is a tool for that in the Arcade SDK, which simplifies the process for
you to post messages to the user's LinkedIn feed either through our Python or
JavaScript SDKs or via LLM tool calling.
Below we are just showing how to use Arcade as an auth provider, if you ever
need to.
"""
# Start the authorization process
auth_response = client.auth.start(
user_id=user_id,
provider="linkedin",
scopes=["w_member_social"],
)
if auth_response.status != "completed":
print("Please complete the authorization challenge in your browser:")
print(auth_response.url)
# Wait for the authorization to complete
auth_response = client.auth.wait_for_completion(auth_response)
if not auth_response.context.token:
raise ValueError("No token found in auth response")
token = auth_response.context.token
user_id = (
None
if not auth_response.context.authorization
else auth_response.context.authorization.user_info.get("sub")
)
if not user_id:
raise ValueError("User ID not found.")
# Prepare the payload data for the LinkedIn API
message = "Hello, from Arcade.dev!"
payload = {
"author": f"urn:li:person:{user_id}",
"lifecycleState": "PUBLISHED",
"specificContent": {
"com.linkedin.ugc.ShareContent": {
"shareCommentary": {"text": message},
"shareMediaCategory": "NONE",
}
},
"visibility": {"com.linkedin.ugc.MemberNetworkVisibility": "PUBLIC"},
}
response = requests.post(
"https://api.linkedin.com/v2/ugcPosts",
headers={"Authorization": f"Bearer {token}"},
json=payload,
)
response.raise_for_status()
print(response.json())
Using LinkedIn auth in custom tools
You can author your own custom tools that interact with LinkedIn APIs.
Use the LinkedIn()
auth class to specify that a tool requires authorization with LinkedIn. The context.authorization.token
field will be automatically populated with the user’s LinkedIn token:
from typing import Annotated
import httpx
from arcade.sdk.errors import ToolExecutionError
from arcade.sdk import ToolContext, tool
from arcade.sdk.auth import LinkedIn
@tool(
requires_auth=LinkedIn(
scopes=["w_member_social"],
)
)
async def create_text_post(
context: ToolContext,
text: Annotated[str, "The text content of the post"],
) -> Annotated[str, "URL of the shared post"]:
"""Share a new text post to LinkedIn."""
endpoint = "/ugcPosts"
# The LinkedIn user ID is required to create a post, even though we're using the user's access token.
# Arcade Engine gets the current user's info from LinkedIn and automatically populates context.authorization.user_info.
# LinkedIn calls the user ID "sub" in their user_info data payload. See:
# https://learn.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin-v2#api-request-to-retreive-member-details
user_id = context.authorization.user_info.get("sub")
if not user_id:
raise ToolExecutionError(
"User ID not found.",
developer_message="User ID not found in `context.authorization.user_info.sub`",
)
headers = {"Authorization": f"Bearer {context.authorization.token}"}
author_id = f"urn:li:person:{user_id}"
payload = {
"author": author_id,
"lifecycleState": "PUBLISHED",
"specificContent": {
"com.linkedin.ugc.ShareContent": {
"shareCommentary": {"text": text},
"shareMediaCategory": "NONE",
}
},
"visibility": {"com.linkedin.ugc.MemberNetworkVisibility": "PUBLIC"},
}
async with httpx.AsyncClient() as client:
response = await client.post(
url=f"https://api.linkedin.com/v2/{endpoint}",
headers=headers,
json=payload,
)
response.raise_for_status()
share_id = response.json().get("id")
return f"https://www.linkedin.com/feed/update/{share_id}/"