-
Notifications
You must be signed in to change notification settings - Fork 55
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
added Seznam SSO provider #194
Changes from 4 commits
da71cad
ddde5e7
ae379b1
cfb5002
3be5d2e
dbede07
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
"""Seznam Login Example""" | ||
|
||
import os | ||
import uvicorn | ||
from fastapi import FastAPI | ||
from fastapi import Request | ||
|
||
from fastapi_sso.sso.seznam import SeznamSSO | ||
|
||
CLIENT_ID = os.environ["CLIENT_ID"] | ||
CLIENT_SECRET = os.environ["CLIENT_SECRET"] | ||
|
||
app = FastAPI() | ||
|
||
sso = SeznamSSO( | ||
client_id=CLIENT_ID, | ||
client_secret=CLIENT_SECRET, | ||
redirect_uri="http://localhost:5000/auth/callback", | ||
allow_insecure_http=True, | ||
) | ||
|
||
|
||
@app.get("/auth/login") | ||
async def auth_init(): | ||
"""Initialize auth and redirect""" | ||
with sso: | ||
return await sso.get_login_redirect() | ||
|
||
|
||
@app.get("/auth/callback") | ||
async def auth_callback(request: Request): | ||
"""Verify login""" | ||
with sso: | ||
user = await sso.verify_and_process(request, params={"client_secret": CLIENT_SECRET}) | ||
return user | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Verify the login implementation and consider filtering sensitive information. The However, passing the |
||
|
||
|
||
if __name__ == "__main__": | ||
uvicorn.run(app="examples.seznam:app", host="127.0.0.1", port=5000) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
"""Seznam SSO Login Helper.""" | ||
|
||
from typing import ClassVar | ||
from typing import Optional | ||
from typing import TYPE_CHECKING | ||
|
||
from fastapi_sso.sso.base import DiscoveryDocument | ||
from fastapi_sso.sso.base import OpenID | ||
from fastapi_sso.sso.base import SSOBase | ||
|
||
if TYPE_CHECKING: | ||
import httpx # pragma: no cover | ||
|
||
|
||
# https://vyvojari.seznam.cz/oauth/doc | ||
|
||
|
||
class SeznamSSO(SSOBase): | ||
"""Class providing login via Seznam OAuth.""" | ||
|
||
provider = "seznam" | ||
base_url = "https://login.szn.cz/api/v1" | ||
scope: ClassVar = ["identity", "avatar"] # + ["contact-phone", "adulthood", "birthday", "gender"] | ||
|
||
async def get_discovery_document(self) -> DiscoveryDocument: | ||
"""Get document containing handy urls.""" | ||
return { | ||
"authorization_endpoint": f"{self.base_url}/oauth/auth", | ||
"token_endpoint": f"{self.base_url}/oauth/token", | ||
"userinfo_endpoint": f"{self.base_url}/user", | ||
} | ||
|
||
async def openid_from_response(self, response: dict, session: Optional["httpx.AsyncClient"] = None) -> OpenID: | ||
"""Return OpenID from user information provided by Seznam.""" | ||
return OpenID( | ||
email=response.get("email"), | ||
first_name=response.get("firstname"), | ||
last_name=response.get("lastname"), | ||
display_name=response.get("accountDisplayName"), | ||
provider=self.provider, | ||
id=response.get("oauth_user_id"), | ||
picture=response.get("avatar_url"), | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is passing the client secret explicitly in
params
neccessary? I would guess oauthlib adds the client secret to the request uri when doingprepare_token_request
inverify_login
method ofSSOBase
🤔 If this is specific to Seznam, I'd probably also add it to documentation, or maybe emphasize it in the comment here so that users who come to documented examples actually notice that this is some specialty :)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, unfortunately it is needed. It took me a while to figure it out, but it's also described in the documentation - "2. Převod kódu na token" contains a "client_secret" field. Without it, Seznam API returns the response "{'error': 'invalid_client'}".
I added a comment to the example - 3be5d2e