fastapi-sso 0.16.0__tar.gz → 0.17.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/PKG-INFO +3 -1
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/README.md +2 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/__init__.py +4 -0
- fastapi_sso-0.17.0/fastapi_sso/sso/bitbucket.py +60 -0
- fastapi_sso-0.17.0/fastapi_sso/sso/discord.py +56 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/pyproject.toml +1 -1
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/LICENSE.md +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/pkce.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/py.typed +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/__init__.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/base.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/facebook.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/fitbit.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/generic.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/github.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/gitlab.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/google.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/kakao.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/line.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/linkedin.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/microsoft.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/naver.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/notion.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/seznam.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/spotify.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/twitter.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/yandex.py +0 -0
- {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/state.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fastapi-sso
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.0
|
|
4
4
|
Summary: FastAPI plugin to enable SSO to most common providers (such as Facebook login, Google login and login via Microsoft Office 365 Account)
|
|
5
5
|
Home-page: https://tomasvotava.github.io/fastapi-sso/
|
|
6
6
|
License: MIT
|
|
@@ -143,6 +143,8 @@ I tend to process Pull Requests faster when properly caffeinated 😉.
|
|
|
143
143
|
- LinkedIn (by Alessandro Pischedda) - [Cereal84](https://github.com/Cereal84)
|
|
144
144
|
- Yandex (by Akim Faskhutdinov) – [akimrx](https://github.com/akimrx)
|
|
145
145
|
- Seznam (by Tomas Koutek) - [TomasKoutek](https://github.com/TomasKoutek)
|
|
146
|
+
- Discord (by Kaelian Baudelet) - [afi-dev](https://github.com/afi-dev)
|
|
147
|
+
- Bitbucket (by Kaelian Baudelet) - [afi-dev](https://github.com/afi-dev)
|
|
146
148
|
|
|
147
149
|
See [Contributing](#contributing) for a guide on how to contribute your own login provider.
|
|
148
150
|
|
|
@@ -116,6 +116,8 @@ I tend to process Pull Requests faster when properly caffeinated 😉.
|
|
|
116
116
|
- LinkedIn (by Alessandro Pischedda) - [Cereal84](https://github.com/Cereal84)
|
|
117
117
|
- Yandex (by Akim Faskhutdinov) – [akimrx](https://github.com/akimrx)
|
|
118
118
|
- Seznam (by Tomas Koutek) - [TomasKoutek](https://github.com/TomasKoutek)
|
|
119
|
+
- Discord (by Kaelian Baudelet) - [afi-dev](https://github.com/afi-dev)
|
|
120
|
+
- Bitbucket (by Kaelian Baudelet) - [afi-dev](https://github.com/afi-dev)
|
|
119
121
|
|
|
120
122
|
See [Contributing](#contributing) for a guide on how to contribute your own login provider.
|
|
121
123
|
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from .sso.base import OpenID, SSOBase, SSOLoginError
|
|
7
|
+
from .sso.bitbucket import BitbucketSSO
|
|
8
|
+
from .sso.discord import DiscordSSO
|
|
7
9
|
from .sso.facebook import FacebookSSO
|
|
8
10
|
from .sso.fitbit import FitbitSSO
|
|
9
11
|
from .sso.generic import create_provider
|
|
@@ -37,4 +39,6 @@ __all__ = [
|
|
|
37
39
|
"NotionSSO",
|
|
38
40
|
"SpotifySSO",
|
|
39
41
|
"TwitterSSO",
|
|
42
|
+
"BitbucketSSO",
|
|
43
|
+
"DiscordSSO",
|
|
40
44
|
]
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""BitBucket SSO Oauth Helper class"""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, ClassVar, List, Optional, Union
|
|
4
|
+
|
|
5
|
+
import pydantic
|
|
6
|
+
|
|
7
|
+
from fastapi_sso.sso.base import DiscoveryDocument, OpenID, SSOBase
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
import httpx # pragma: no cover
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BitbucketSSO(SSOBase):
|
|
14
|
+
"""Class providing login using BitBucket OAuth"""
|
|
15
|
+
|
|
16
|
+
provider = "bitbucket"
|
|
17
|
+
scope: ClassVar = ["account", "email"]
|
|
18
|
+
version = "2.0"
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
client_id: str,
|
|
23
|
+
client_secret: str,
|
|
24
|
+
redirect_uri: Optional[Union[pydantic.AnyHttpUrl, str]] = None,
|
|
25
|
+
allow_insecure_http: bool = False,
|
|
26
|
+
scope: Optional[List[str]] = None,
|
|
27
|
+
):
|
|
28
|
+
super().__init__(
|
|
29
|
+
client_id=client_id,
|
|
30
|
+
client_secret=client_secret,
|
|
31
|
+
redirect_uri=redirect_uri,
|
|
32
|
+
allow_insecure_http=allow_insecure_http,
|
|
33
|
+
scope=scope,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
async def get_useremail(self, session: Optional["httpx.AsyncClient"] = None) -> dict:
|
|
37
|
+
"""Get user email"""
|
|
38
|
+
if session is None:
|
|
39
|
+
raise ValueError("Session is required to make HTTP requests")
|
|
40
|
+
|
|
41
|
+
response = await session.get(f"https://api.bitbucket.org/{self.version}/user/emails")
|
|
42
|
+
return response.json()
|
|
43
|
+
|
|
44
|
+
async def get_discovery_document(self) -> DiscoveryDocument:
|
|
45
|
+
return {
|
|
46
|
+
"authorization_endpoint": "https://bitbucket.org/site/oauth2/authorize",
|
|
47
|
+
"token_endpoint": "https://bitbucket.org/site/oauth2/access_token",
|
|
48
|
+
"userinfo_endpoint": f"https://api.bitbucket.org/{self.version}/user",
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async def openid_from_response(self, response: dict, session: Optional["httpx.AsyncClient"] = None) -> OpenID:
|
|
52
|
+
email = await self.get_useremail(session=session)
|
|
53
|
+
return OpenID(
|
|
54
|
+
email=email["values"][0]["email"],
|
|
55
|
+
display_name=response.get("display_name"),
|
|
56
|
+
provider=self.provider,
|
|
57
|
+
id=str(response.get("uuid")).strip("{}"),
|
|
58
|
+
first_name=response.get("nickname"),
|
|
59
|
+
picture=response.get("links", {}).get("avatar", {}).get("href"),
|
|
60
|
+
)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Discord SSO Oauth Helper class"""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, ClassVar, List, Optional, Union
|
|
4
|
+
|
|
5
|
+
import pydantic
|
|
6
|
+
|
|
7
|
+
from fastapi_sso.sso.base import DiscoveryDocument, OpenID, SSOBase
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
import httpx # pragma: no cover
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DiscordSSO(SSOBase):
|
|
14
|
+
"""Class providing login using Discord OAuth"""
|
|
15
|
+
|
|
16
|
+
provider = "discord"
|
|
17
|
+
scope: ClassVar = ["identify", "email", "openid"]
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
client_id: str,
|
|
22
|
+
client_secret: str,
|
|
23
|
+
redirect_uri: Optional[Union[pydantic.AnyHttpUrl, str]] = None,
|
|
24
|
+
allow_insecure_http: bool = False,
|
|
25
|
+
scope: Optional[List[str]] = None,
|
|
26
|
+
):
|
|
27
|
+
super().__init__(
|
|
28
|
+
client_id=client_id,
|
|
29
|
+
client_secret=client_secret,
|
|
30
|
+
redirect_uri=redirect_uri,
|
|
31
|
+
allow_insecure_http=allow_insecure_http,
|
|
32
|
+
scope=scope,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
async def get_discovery_document(self) -> DiscoveryDocument:
|
|
36
|
+
return {
|
|
37
|
+
"authorization_endpoint": "https://discord.com/oauth2/authorize",
|
|
38
|
+
"token_endpoint": "https://discord.com/api/oauth2/token",
|
|
39
|
+
"userinfo_endpoint": "https://discord.com/api/users/@me",
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async def openid_from_response(self, response: dict, session: Optional["httpx.AsyncClient"] = None) -> OpenID:
|
|
43
|
+
user_id = response.get("id")
|
|
44
|
+
avatar = response.get("avatar")
|
|
45
|
+
picture = None
|
|
46
|
+
if user_id and avatar:
|
|
47
|
+
picture = f"https://cdn.discordapp.com/avatars/{user_id}/{avatar}.png"
|
|
48
|
+
|
|
49
|
+
return OpenID(
|
|
50
|
+
email=response.get("email"),
|
|
51
|
+
display_name=response.get("global_name"),
|
|
52
|
+
provider=self.provider,
|
|
53
|
+
id=user_id,
|
|
54
|
+
first_name=response.get("username"),
|
|
55
|
+
picture=picture,
|
|
56
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "fastapi-sso"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.17.0"
|
|
4
4
|
description = "FastAPI plugin to enable SSO to most common providers (such as Facebook login, Google login and login via Microsoft Office 365 Account)"
|
|
5
5
|
authors = ["Tomas Votava <info@tomasvotava.eu>"]
|
|
6
6
|
readme = "README.md"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|