Authentication Schemes Strategy¶
Authentication scheme is another strategy for identifying the user who is using the application. The difference between it and and Guard strategy is your identification executed at middleware layer when processing incoming request while guard execution happens just before route function is executed.
Ellar provides BaseAuthenticationHandler contract which defines what is required to set up any authentication strategy. We are going to make some modifications on the existing project to see how we can achieve the same result and to show how authentication handlers in ellar.
Creating a JWT Authentication Handler¶
Just like AuthGuard, we need to create its equivalent. But first we need to create a auth_scheme.py at the root level of your application for us to define a JWTAuthentication handler. 
| project_name/auth_scheme.py | |
|---|---|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |  | 
Let us make JWTAuthentication Handler available for ellar to use as shown below
| project_name.server.py | |
|---|---|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |  | 
GlobalGuard registration we did in AuthModule, so that we don't have too user identification checks. Note
In the above illustration, we added JWTAuthentication as a type. This means DI will create JWTAuthentication instance. We can use this method because we want JWTService to be injected when instantiating JWTAuthentication. But if you don't have any need for DI injection, you can use the below. 
...
application.add_authentication_schemes(JWTAuthentication())
## OR
## use_authentication_schemes(JWTAuthentication())
We need to refactor auth controller and mark refresh_token and sign_in function as public routes by using SkipAuth decorator from ellar.auth package.
| auth/controller.py | |
|---|---|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |  | 
@AuthenticationRequired('JWTAuthentication') to ensure we have authenticated user before executing any route function and, we passed in JWTAuthentication as a parameter, which will be used in openapi doc to define the controller routes security scheme. It is importance to note that when using AuthenticationHandler approach, that you have to always use AuthenticationRequired decorator on route functions or controller that needs protected from anonymous users.
But if you have a single form of authentication, you can register AuthenticatedRequiredGuard from eellar.auth.guard module globally just like we did in applying guard globally
| auth/module.py | |
|---|---|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |  | 
Still having the server running, we can test as before
$ # GET /auth/profile
$ curl http://localhost:8000/auth/profile
{"detail":"Forbidden"} # status_code=403
$ # POST /auth/login
$ curl -X POST http://localhost:8000/auth/login -d '{"username": "john", "password": "password"}' -H "Content-Type: application/json"
{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTg3OTE0OTE..."}
$ # GET /profile using access_token returned from previous step as bearer code
$ curl http://localhost:8000/auth/profile -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2Vybm..."
{"exp":1698793558,"iat":1698793258,"jti":"e96e94c5c3ef4fbbbd7c2468eb64534b","sub":1,"user_id":1,"username":"john", "id":null,"auth_type":"bearer"}