Skip to content

Commit d6a6c0b

Browse files
committed
feat: add callback_raw to client
1 parent 7cc3d78 commit d6a6c0b

4 files changed

Lines changed: 19 additions & 11 deletions

File tree

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pip install fastlink
2525
## Get Started
2626

2727
```python
28-
from typing import Annotated
28+
from typing import Annotated, Any
2929

3030
from fastapi import Depends, FastAPI
3131
from fastapi.responses import RedirectResponse
@@ -54,7 +54,6 @@ async def login() -> RedirectResponse:
5454
async def callback(call: Annotated[OAuth2Callback, Depends()]) -> OpenID:
5555
async with sso:
5656
return await sso.callback(call)
57-
5857
```
5958

6059
Now you can run the server and visit `http://localhost:8000/login` to start the OAuth 2.0 flow.

examples/jwt.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from typing import Annotated
22

33
from fastapi import Depends, FastAPI, Form, HTTPException, Response
4+
from starlette import status
45

56
from fastlink.exceptions import FastLinkError
67
from fastlink.integrations.fastapi.transport import CookieTransport
@@ -17,7 +18,7 @@
1718
@app.post("/login")
1819
def login(form: Annotated[OAuth2PasswordRequest, Form()]) -> Response:
1920
if form.username != "admin" or form.password != "admin": # noqa: S105
20-
raise HTTPException(status_code=400, detail="Incorrect username or password")
21+
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Incorrect username or password")
2122
token = manager.create("access", JWTPayload(sub=form.username))
2223
return transport.set_token(Response(), token)
2324

@@ -27,5 +28,5 @@ def get_me(token: Annotated[str, Depends(transport)]) -> JWTPayload:
2728
try:
2829
payload = manager.validate("access", token)
2930
except FastLinkError as e:
30-
raise HTTPException(status_code=401, detail="Invalid token") from e
31+
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token") from e
3132
return payload

fastlink/base/client.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,12 @@ async def login_url(
9898

9999
async def login(
100100
self,
101-
callback: OAuth2Callback,
101+
call: OAuth2Callback,
102102
*,
103103
body: dict[str, Any] | None = None,
104104
headers: dict[str, str] | None = None,
105105
) -> TokenResponse:
106-
request = self._prepare_token_request(callback, body=body, headers=headers)
106+
request = self._prepare_token_request(call, body=body, headers=headers)
107107
auth = httpx.BasicAuth(self.client_id, self.client_secret)
108108
response = await self.client.send(
109109
request,
@@ -126,9 +126,13 @@ async def userinfo(self) -> dict[str, Any]:
126126
raise UserinfoError("Getting userinfo failed: %s", content)
127127
return cast("dict[str, Any]", content)
128128

129+
async def callback_raw(self, call: OAuth2Callback) -> dict[str, Any]:
130+
await self.login(call)
131+
return await self.userinfo()
132+
129133
def _prepare_token_request(
130134
self,
131-
callback: OAuth2Callback,
135+
call: OAuth2Callback,
132136
*,
133137
body: dict[str, Any] | None = None,
134138
headers: dict[str, str] | None = None,
@@ -138,13 +142,13 @@ def _prepare_token_request(
138142
headers = headers or {}
139143
headers |= {"Content-Type": "application/x-www-form-urlencoded"}
140144
if self.use_state:
141-
if not callback.state:
145+
if not call.state:
142146
raise StateError("State was not found in the callback")
143-
body |= {"state": callback.state}
147+
body |= {"state": call.state}
144148
body = {
145149
"grant_type": "authorization_code",
146-
"code": callback.code,
147-
"redirect_uri": callback.redirect_uri or self.redirect_uri,
150+
"code": call.code,
151+
"redirect_uri": call.redirect_uri or self.redirect_uri,
148152
"client_id": self.client_id,
149153
"client_secret": self.client_secret,
150154
**body,

fastlink/telegram/provider.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ async def userinfo(self) -> dict[str, Any]:
101101
assert self._callback is not None
102102
return self._callback.model_dump(exclude_none=True)
103103

104+
async def callback_raw(self, call: TelegramCallback) -> dict[str, Any]:
105+
await self.login(call)
106+
return await self.userinfo()
107+
104108
async def openid_from_response(self, response: dict[str, Any]) -> OpenID:
105109
first_name, last_name = (
106110
response["first_name"],

0 commit comments

Comments
 (0)