Skip to content

Commit

Permalink
Add new backend for LinkedIn OpenID Connect (#833)
Browse files Browse the repository at this point in the history
* create linkedin openid connect backend

* add docstring with link to official docs and deprecation notice for oauth2

* define oidc endpoint for linkedin

* override token auth method to provide client id and secret in payload (not basic auth)

* copy and override validate_claims to remove not support nonce validation

* remove already disabled code section for nonce check

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* add test case for linkedin openid (still breaking, inspired from google)

* skip invalid nonce test as linkedin does not provide any nonce

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
noxan and pre-commit-ci[bot] authored Oct 31, 2023
1 parent 9c630a6 commit e0cb888
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
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"

# 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


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

0 comments on commit e0cb888

Please sign in to comment.