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 AI.
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
How you configure the LinkedIn auth provider depends on whether you use the Arcade Cloud Engine or a self-hosted Engine.
With the Arcade Cloud Engine, you can start building and testing LinkedIn auth without any configuration. Your users will see Arcade AI (demo)
as the name of the application that's requesting permission.
When you are ready to go to production, you'll want to configure the LinkedIn auth provider with your own LinkedIn app credentials, so users see your app name when they authorize access.
Create a LinkedIn app
- Follow LinkedIn's guide to setting up user authorization (opens in a new tab)
- Choose the permissions you need for your app
- Set the redirect URL to:
https://cloud.arcade-ai.com/api/v1/oauth/callback
- Copy the client ID and client secret
Configuring LinkedIn auth with the Arcade Cloud Engine
Coming soon! In 0.1.0-preview, the Arcade Cloud Engine does not yet support configuring auth providers.
Configuring LinkedIn auth with a self-hosted Arcade Engine
Set environment variables
Set the following environment variables:
export LINKEDIN_CLIENT_ID="<your client ID>"
export LINKEDIN_CLIENT_SECRET="<your client secret>"
Or, you can set these values in a .env
file:
LINKEDIN_CLIENT_ID="<your client ID>"
LINKEDIN_CLIENT_SECRET="<your client secret>"
See Engine configuration for more information on how to set environment variables and configure the Arcade Engine.
Edit the Engine configuration
Edit the engine.yaml
file and add a linkedin
item to the auth.providers
section:
auth:
providers:
- id: linkedin
client_id: ${env:LINKEDIN_CLIENT_ID}
client_secret: ${env:LINKEDIN_CLIENT_SECRET}
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:
from arcadepy import Arcade
client = Arcade() # Automatically finds the `ARCADE_API_KEY` env variable
user_id = "[email protected]"
# 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.authorization_url)
# Wait for the authorization to complete
auth_response = client.auth.wait_for_completion(auth_response)
token = auth_response.context.token
# TODO: Do something interesting with the token...
Using LinkedIn auth in custom tools
The Arcade LLM API is a convenient way to call LLMs and automatically invoke 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}/"