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.
Files changed (28) hide show
  1. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/PKG-INFO +3 -1
  2. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/README.md +2 -0
  3. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/__init__.py +4 -0
  4. fastapi_sso-0.17.0/fastapi_sso/sso/bitbucket.py +60 -0
  5. fastapi_sso-0.17.0/fastapi_sso/sso/discord.py +56 -0
  6. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/pyproject.toml +1 -1
  7. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/LICENSE.md +0 -0
  8. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/pkce.py +0 -0
  9. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/py.typed +0 -0
  10. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/__init__.py +0 -0
  11. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/base.py +0 -0
  12. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/facebook.py +0 -0
  13. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/fitbit.py +0 -0
  14. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/generic.py +0 -0
  15. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/github.py +0 -0
  16. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/gitlab.py +0 -0
  17. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/google.py +0 -0
  18. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/kakao.py +0 -0
  19. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/line.py +0 -0
  20. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/linkedin.py +0 -0
  21. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/microsoft.py +0 -0
  22. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/naver.py +0 -0
  23. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/notion.py +0 -0
  24. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/seznam.py +0 -0
  25. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/spotify.py +0 -0
  26. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/twitter.py +0 -0
  27. {fastapi_sso-0.16.0 → fastapi_sso-0.17.0}/fastapi_sso/sso/yandex.py +0 -0
  28. {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.16.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.16.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