Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new backend for LinkedIn OpenID Connect #833

Merged
merged 9 commits into from
Oct 31, 2023
38 changes: 37 additions & 1 deletion social_core/backends/linkedin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,47 @@
LinkedIn OAuth1 and OAuth2 backend, docs at:
https://python-social-auth.readthedocs.io/en/latest/backends/linkedin.html
"""
from social_core.exceptions import AuthCanceled
import datetime
from calendar import timegm

from social_core.backends.open_id_connect import OpenIdConnectAuth
from social_core.exceptions import AuthCanceled, AuthTokenError

from .oauth import BaseOAuth2


class LinkedinOpenIdConnect(OpenIdConnectAuth):
"""
Linkedin OpenID Connect backend. Oauth2 has been deprecated as of August 1, 2023.
https://learn.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin-v2?context=linkedin/consumer/context
"""

name = "linkedin-openidconnect"
# Settings from https://www.linkedin.com/oauth/.well-known/openid-configuration
OIDC_ENDPOINT = "https://www.linkedin.com/oauth"

noxan marked this conversation as resolved.
Show resolved Hide resolved
# https://developer.okta.com/docs/reference/api/oidc/#response-example-success-9
# Override this value as it is not provided by Linkedin.
# else our request falls back to basic auth which is not supported.
TOKEN_ENDPOINT_AUTH_METHOD = "client_secret_post"

def validate_claims(self, id_token):
"""Copy of the regular validate_claims method without the nonce validation."""

utc_timestamp = timegm(datetime.datetime.utcnow().utctimetuple())

if "nbf" in id_token and utc_timestamp < id_token["nbf"]:
raise AuthTokenError(self, "Incorrect id_token: nbf")

# Verify the token was issued in the last 10 minutes
iat_leeway = self.setting("ID_TOKEN_MAX_AGE", self.ID_TOKEN_MAX_AGE)
if utc_timestamp > id_token["iat"] + iat_leeway:
raise AuthTokenError(self, "Incorrect id_token: iat")

# Skip the nonce validation for linkedin as it does not provide any nonce.
# https://stackoverflow.com/questions/76889585/issues-with-sign-in-with-linkedin-using-openid-connect
noxan marked this conversation as resolved.
Show resolved Hide resolved


class LinkedinOAuth2(BaseOAuth2):
name = "linkedin-oauth2"
AUTHORIZATION_URL = "https://www.linkedin.com/oauth/v2/authorization"
Expand Down
38 changes: 38 additions & 0 deletions social_core/tests/backends/test_linkedin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,44 @@
import json

from .oauth import OAuth2Test
from .test_open_id_connect import OpenIdConnectTestMixin


class LinkedinOpenIdConnectTest(OpenIdConnectTestMixin, OAuth2Test):
backend_path = "social_core.backends.linkedin.LinkedinOpenIdConnect"
user_data_url = "https://api.linkedin.com/v2/userinfo"
issuer = "https://www.linkedin.com"
openid_config_body = json.dumps(
{
"issuer": "https://www.linkedin.com",
"authorization_endpoint": "https://www.linkedin.com/oauth/v2/authorization",
"token_endpoint": "https://www.linkedin.com/oauth/v2/accessToken",
"userinfo_endpoint": "https://api.linkedin.com/v2/userinfo",
"jwks_uri": "https://www.linkedin.com/oauth/openid/jwks",
"response_types_supported": ["code"],
"subject_types_supported": ["pairwise"],
"id_token_signing_alg_values_supported": ["RS256"],
"scopes_supported": ["openid", "profile", "email"],
"claims_supported": [
"iss",
"aud",
"iat",
"exp",
"sub",
"name",
"given_name",
"family_name",
"picture",
"email",
"email_verified",
"locale",
],
}
)

def test_invalid_nonce(self):
"""Skip the invalid nonce test as LinkedIn does not provide any nonce."""
pass


class BaseLinkedinTest:
Expand Down