-
-
Notifications
You must be signed in to change notification settings - Fork 548
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add new backend
BitbucketDataCenterOAuth2
(#856)
* feat: add new backend BitbucketDataCenterOAuth2 * abstract away PKCE logic in BaseOAuth2PKCE for reuse * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * abstract away PKCE logic in BaseOAuth2PKCE for reuse * noqa flake8 line length rule for URLs in comments * chore: add BitbucketDataCenterOAuth2Test * chore: abstract PKCE tests in OAuth2PkcePlainTest, OAuth2PkceS256Test * noqa flake8 line length rule for URLs in comments * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * chore: fix isort errors * chore: improvements, address review suggestions * fix: docs URL * Apply suggestions from code review Co-authored-by: Johan Castiblanco <51926076+johanv26@users.noreply.github.com> --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Johan Castiblanco <51926076+johanv26@users.noreply.github.com>
- Loading branch information
1 parent
a670659
commit 51ff887
Showing
6 changed files
with
395 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
""" | ||
Bitbucket Data Center OAuth2 backend, docs at: | ||
https://python-social-auth.readthedocs.io/en/latest/backends/bitbucket_datacenter_oauth2.html | ||
https://confluence.atlassian.com/bitbucketserver/bitbucket-oauth-2-0-provider-api-1108483661.html | ||
""" | ||
|
||
from .oauth import BaseOAuth2PKCE | ||
|
||
|
||
class BitbucketDataCenterOAuth2(BaseOAuth2PKCE): | ||
""" | ||
Implements client for Bitbucket Data Center OAuth 2.0 provider API. | ||
ref: https://confluence.atlassian.com/bitbucketserver/bitbucket-oauth-2-0-provider-api-1108483661.html | ||
""" | ||
|
||
name = "bitbucket-datacenter-oauth2" | ||
ID_KEY = "id" | ||
SCOPE_SEPARATOR = " " | ||
ACCESS_TOKEN_METHOD = "POST" | ||
REFRESH_TOKEN_METHOD = "POST" | ||
REDIRECT_STATE = False | ||
STATE_PARAMETER = True | ||
# ref: https://confluence.atlassian.com/bitbucketserver/bitbucket-oauth-2-0-provider-api-1108483661.html#BitbucketOAuth2.0providerAPI-scopes # noqa | ||
DEFAULT_SCOPE = ["PUBLIC_REPOS"] | ||
USE_BASIC_AUTH = False | ||
EXTRA_DATA = [ | ||
("token_type", "token_type"), | ||
("access_token", "access_token"), | ||
("refresh_token", "refresh_token"), | ||
("expires_in", "expires"), | ||
("scope", "scope"), | ||
# extra user profile fields | ||
("first_name", "first_name"), | ||
("last_name", "last_name"), | ||
("email", "email"), | ||
("name", "name"), | ||
("username", "username"), | ||
("display_name", "display_name"), | ||
("type", "type"), | ||
("active", "active"), | ||
("url", "url"), | ||
("avatar_url", "avatar_url"), | ||
] | ||
PKCE_DEFAULT_CODE_CHALLENGE_METHOD = "s256" # can be "plain" or "s256" | ||
PKCE_DEFAULT_CODE_VERIFIER_LENGTH = 48 # must be b/w 43-127 chars | ||
DEFAULT_USE_PKCE = True | ||
DEFAULT_USER_AVATAR_SIZE = 48 | ||
|
||
@property | ||
def server_base_oauth2_api_url(self) -> str: | ||
base_url = self.setting("URL") | ||
return f"{base_url}/rest/oauth2/latest" | ||
|
||
@property | ||
def server_base_rest_api_url(self) -> str: | ||
base_url = self.setting("URL") | ||
return f"{base_url}/rest/api/latest" | ||
|
||
def authorization_url(self) -> str: | ||
return f"{self.server_base_oauth2_api_url}/authorize" | ||
|
||
def access_token_url(self) -> str: | ||
return f"{self.server_base_oauth2_api_url}/token" | ||
|
||
def get_user_details(self, response) -> dict: | ||
"""Return user details for the Bitbucket Data Center account""" | ||
# `response` here is the return value of `user_data` method | ||
user_data = response | ||
_, first_name, last_name = self.get_user_names(user_data["displayName"]) | ||
uid = self.get_user_id(details=None, response=response) | ||
return { | ||
"uid": uid, | ||
"first_name": first_name, | ||
"last_name": last_name, | ||
"email": user_data["emailAddress"], | ||
"name": user_data["name"], | ||
"username": user_data["slug"], | ||
"display_name": user_data["displayName"], | ||
"type": user_data["type"], | ||
"active": user_data["active"], | ||
"url": user_data["links"]["self"][0]["href"], | ||
"avatar_url": user_data["avatarUrl"], | ||
} | ||
|
||
def user_data(self, access_token, *args, **kwargs) -> dict: | ||
"""Fetch user data from Bitbucket Data Center REST API""" | ||
# At this point, we don't know the current user's username | ||
# and Bitbucket doesn't provide any API to do so. | ||
# However, the current user's username is sent in every response header. | ||
# ref: https://community.developer.atlassian.com/t/obtain-authorised-users-username-from-api/24422/2 # noqa | ||
headers = {"Authorization": f"Bearer {access_token}"} | ||
response = self.request( | ||
url=f"{self.server_base_rest_api_url}/application-properties", | ||
method="GET", | ||
headers=headers, | ||
) | ||
# ref: https://developer.atlassian.com/server/bitbucket/rest/v815/api-group-system-maintenance/#api-api-latest-users-userslug-get # noqa | ||
username = response.headers["x-ausername"] | ||
return self.get_json( | ||
url=f"{self.server_base_rest_api_url}/users/{username}", | ||
headers=headers, | ||
params={ | ||
"avatarSize": self.setting( | ||
"USER_AVATAR_SIZE", default=self.DEFAULT_USER_AVATAR_SIZE | ||
) # to force `avatarUrl` in response | ||
}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.