@@ -73,7 +73,6 @@ class UsersService:
7373 found_user = next (filtered_list)
7474 if found_user:
7575 return UserModel(** found_user)
76- return found_user
7776
7877```
7978
@@ -95,8 +94,6 @@ class UserModule(ModuleBase):
9594 User Module
9695 """
9796
98- pass
99-
10097```
10198
10299### ** Implementing the "Sign in" endpoint**
@@ -191,8 +188,6 @@ class AuthModule(ModuleBase):
191188 """
192189 Auth Module
193190 """
194-
195- pass
196191```
197192
198193In the above example, we configured ` JWTModule ` with very minimal configurations and registered it as a module dependency
@@ -443,7 +438,7 @@ With the above illustration refresh token mechanism is complete.
443438You can also vist [ http://localhost:8000/docs ] ( http://localhost:8000/docs )
444439![ Swagger UI] ( ../img/auth_image.png )
445440
446- ## Apply AuthGuard Globally
441+ ## ** Apply AuthGuard Globally**
447442
448443In situations when you need to protect all your endpoints, you can register ` AuthGuard ` as a global guard instead of
449444using the ` @UseGuards ` decorator in all your controllers or route functions.
@@ -479,8 +474,6 @@ class AuthModule(ModuleBase):
479474 """
480475 Auth Module
481476 """
482-
483- pass
484477```
485478
486479With this, ` AuthGuard ` will be available to all endpoints.
@@ -613,6 +606,7 @@ class AuthController(ControllerBase):
613606 async def refresh_token (self , payload : str = Body(embed = True )):
614607 return await self .auth_service.refresh_token(payload)
615608```
609+ Source Code to this example is [ here] ( )
616610
617611## ** 2. Authentication Schemes**
618612
@@ -639,8 +633,6 @@ from ellar.common import IHostContext
639633from ellar.di import injectable
640634from ellar_jwt import JWTService
641635
642- from starlette.exceptions import HTTPException
643-
644636
645637@injectable
646638class JWTAuthentication (HttpBearerAuthenticationHandler ):
@@ -657,8 +649,8 @@ class JWTAuthentication(HttpBearerAuthenticationHandler):
657649 data = await self .jwt_service.decode_async(credentials.credentials)
658650 return UserIdentity(auth_type = self .scheme, ** data)
659651 except Exception as ex:
660- # if we cant identity the user or token has expired we raise 401 error .
661- raise HTTPException( status_code = 401 ) from ex
652+ # if we cant identity the user or token has expired, we return None .
653+ return None
662654```
663655
664656Let us make ` JWTAuthentication ` Handler available for ellar to use as shown below
@@ -680,46 +672,31 @@ application.add_authentication_schemes(JWTAuthentication)
680672
681673```
682674Unlike guards, Authentication handlers are registered global by default as shown in the above illustration.
683- Also, we need to remove ` GlobalGuard ` registration we did in ` AuthModule ` , so that we dont have too user identification checks.
675+ Also, we need to remove ` GlobalGuard ` registration we did in ` AuthModule ` ,
676+ so that we don't have too user identification checks.
684677
685678!!!note
686- In the above illustration, we added JWTAuthentication as a type. This means JWTAuthentication instance will be created by DI. We can using this method because we want to inject ` JWTService ` .
679+ In the above illustration, we added JWTAuthentication as a type.
680+ This means DI will create JWTAuthentication instance.
681+ We can use this method because we want ` JWTService ` to be injected when instantiating ` JWTAuthentication ` .
687682 But if you don't have any need for DI injection, you can use the below.
688683 ```python
689684 ...
690685 application.add_authentication_schemes(JWTAuthentication())
691686 ```
692687
693- Next, we register a simple guard ` AuthenticationRequiredGuard ` globally to the application. ` AuthenticationRequiredGuard ` is a simply guard
694- that checks if a request has a valid user identity.
695-
696- ``` python title='project_name.server.py' linenums='1'
697- import os
698- from ellar.common.constants import ELLAR_CONFIG_MODULE
699- from ellar.core.factory import AppFactory
700- from ellar.auth.guard import AuthenticatedRequiredGuard
701- from .root_module import ApplicationModule
702- from .auth_scheme import JWTAuthentication
703-
704-
705- application = AppFactory.create_from_app_module(
706- ApplicationModule,
707- config_module = os.environ.get(
708- ELLAR_CONFIG_MODULE , " project_name.config:DevelopmentConfig"
709- ),
710- global_guards = [AuthenticatedRequiredGuard(' JWTAuthentication' )]
711- )
712- application.add_authentication_schemes(JWTAuthentication)
713- ```
714- We need to refactor auth controller and mark refresh and sign_in function as public routes
688+ We need
689+ to refactor auth controller and mark ` refresh_token ` and ` sign_in ` function as public routes
690+ by using ` SkipAuth ` decorator from ` ellar.auth ` package.
715691
716692``` python title='auth.controller.py' linenums='1'
717693from ellar.common import Controller, ControllerBase, post, Body, get
718- from ellar.auth import SkipAuth
694+ from ellar.auth import SkipAuth, AuthenticationRequired
719695from ellar.openapi import ApiTags
720696from .services import AuthService
721697
722698
699+ @AuthenticationRequired (' JWTAuthentication' )
723700@Controller
724701@ApiTags (name = ' Authentication' , description = ' User Authentication Endpoints' )
725702class AuthController (ControllerBase ):
@@ -742,6 +719,50 @@ class AuthController(ControllerBase):
742719
743720
744721```
722+ In the above illustration,
723+ we decorated AuthController with ` @AuthenticationRequired('JWTAuthentication') `
724+ to ensure we have authenticated user before executing any route function and,
725+ we passed in ` JWTAuthentication ` as a parameter,
726+ which will be used in openapi doc to define the controller routes security scheme.
727+
728+ It is importance to note that when using ` AuthenticationHandler ` approach,
729+ that you have
730+ to always use ` AuthenticationRequired ` decorator on route functions or controller
731+ that needs protected from anonymous users.
732+
733+ But if you have a single form of authentication,
734+ you can register ` AuthenticatedRequiredGuard ` from ` eellar.auth.guard ` module globally
735+ just like we did in [ applying guard globally] ( #apply-authguard-globally )
736+
737+ ``` python title='auth.module.py' linenums='1'
738+ from datetime import timedelta
739+ from ellar.auth.guard import AuthenticatedRequiredGuard
740+ from ellar.common import GlobalGuard, Module
741+ from ellar.core import ModuleBase
742+ from ellar.di import ProviderConfig
743+ from ellar_jwt import JWTModule
744+
745+ from ..users.module import UsersModule
746+ from .controllers import AuthController
747+ from .services import AuthService
748+
749+
750+ @Module (
751+ modules = [
752+ UsersModule,
753+ JWTModule.setup(
754+ signing_secret_key = " my_poor_secret_key_lol" , lifetime = timedelta(minutes = 5 )
755+ ),
756+ ],
757+ controllers = [AuthController],
758+ providers = [AuthService, ProviderConfig(GlobalGuard, use_value = AuthenticatedRequiredGuard(' JWTAuthentication' , []))],
759+ )
760+ class AuthModule (ModuleBase ):
761+ """
762+ Auth Module
763+ """
764+ ```
765+
745766Still having the server running, we can test as before
746767
747768``` shell
@@ -758,3 +779,4 @@ $ curl http://localhost:8000/auth/profile -H "Authorization: Bearer eyJhbGciOiJI
758779{" exp" :1698793558," iat" :1698793258," jti" :" e96e94c5c3ef4fbbbd7c2468eb64534b" ," sub" :1," user_id" :1," username" :" john" , " id" :null," auth_type" :" bearer" }
759780
760781```
782+ Source Code to this example is [ here] ( )
0 commit comments