Social Router¶
The Social router will generate a set of endpoints for Social Authentication users.
- GET
/{provider}
- GET
/{provider}/callback
Setup the Social Router¶
To Setup the Social authentication service, you will need to add all
requirements to the object SocialService
.
from authx.services import SocialService
from authx.backend import UsersRepo
from authx.core.jwt import JWTBackend
SocialService.setup(
repo = UserRepo,
auth_backend = JWTBackend,
base_url = 'http://localhost:8000',
option = 'social',
)
This one gonna help use to use the authentication service, that we provide.
from authx import Authentication
from fastapi import FastAPI
app = FastAPI()
auth = Authentication()
app.include_router(auth.social_router, prefix="/auth")
Info
We describe the SocialService
object in the
Social Service documentation.
Login¶
Using GET
Method to login, after provide all parameters like the provider
(ex. Facebook,Google,etc), request
, all of that gonna return a
`RedirectResponse where we gonna redirect the user to the provider.
@router.get("/{provider}", name="social:login")
async def login(*, provider: str, request: Request):
check_provider(provider)
service = SocialService()
method = getattr(service, f"login_{provider}")
state = hashlib.sha256(os.urandom(1024)).hexdigest()
request.session["state"] = state
redirect_uri = method(state)
return RedirectResponse(redirect_uri)
Before, send the request to the provider, we gonna check if the provider is valid.
def check_provider(provider):
if provider not in social_providers:
raise HTTPException(404)
Info
Until Now AuthX Support the following providers:
* Facebook : [Read More](../social/facebook.md)
* Google : [Read More](../social/google.md)
After checking the Provider, we gonna check if the SocialService is setup, and
then the method login_{provider}
is available.
Callback¶
Same as the login
method, the Callback is based on GET
method, with the same
Arguments, but with a different return, cause here we gonna return an
HTMLResponse
that gonna redirect the user to the home page.
As always, we gonna check first if the provider
is valid, and then we gonna
check if the state
is valid.
@router.get("/{provider}/callback", name="social:callback")
async def callback(*, provider: str, request: Request):
check_provider(provider)
state_query = request.query_params.get("state")
state_session = request.session.get("state")
if not check_state(state_query, state_session):
raise HTTPException(403)
Warning
if The stale is not valid we gonna raise an HTTPException with a status code of 403.
Now we gonna Create code
where we gonna get a query_params
with the code
from the provider, without forgetting the SocialService
, and the Method where
we gonna callback the provider.
code = request.query_params.get("code")
service = SocialService()
method = getattr(service, f"callback_{provider}")
sid, email = await method(code)
Now, lets try to create the token and redirect the user to the home page, the
response use set_cookie
to set the token in the cookie.
response.set_cookie(
key=access_cookie_name,
value=tokens.get("access"),
secure=not debug,
httponly=True,
max_age=access_expiration,
)
response.set_cookie(
key=refresh_cookie_name,
value=tokens.get("refresh"),
secure=not debug,
httponly=True,
max_age=refresh_expiration,
)
Now if the user is not logged in, we gonna redirect a SocialException
as an
HTMLReponse
with a status_code
.
return response
except SocialException as e:
return HTMLResponse(e.content, status_code=e.status_code)
Full Callback¶
@router.get("/{provider}/callback", name="social:callback")
async def callback(*, provider: str, request: Request):
check_provider(provider)
state_query = request.query_params.get("state")
state_session = request.session.get("state")
if not check_state(state_query, state_session):
raise HTTPException(403)
code = request.query_params.get("code")
service = SocialService()
method = getattr(service, f"callback_{provider}")
sid, email = await method(code)
try:
tokens = await service.resolve_user(provider, sid, email)
response = RedirectResponse("/")
response.set_cookie(
key=access_cookie_name,
value=tokens.get("access"),
secure=not debug,
httponly=True,
max_age=access_expiration,
)
response.set_cookie(
key=refresh_cookie_name,
value=tokens.get("refresh"),
secure=not debug,
httponly=True,
max_age=refresh_expiration,
)
return response
except SocialException as e:
return HTMLResponse(e.content, status_code=e.status_code)
return router
Info
Also, an Addons is available to add some utility functions to the social login, for example captcha, email verification, etc.