auth setup
swadhinbiswas committed 2 years ago
aa0cc75
1 parent 9b79e1d
commit aa0cc75
4 files changed
+110 -9
Showing 4 changed files+110-9
▼backend/auth/auth_hader.py
+37-0
| @@ -0,0 +1,37 @@ | ||
1 | +from typing import NamedTuple | |
2 | + | |
3 | +from expreance import BadCredentialsException,RequiresAuthenticationException | |
4 | +from starlette.requests import Request as StarletteRequest | |
5 | + | |
6 | +class AuthorizationHeaderElements(NamedTuple): | |
7 | + authorization_scheme: str | |
8 | + bearer_token: str | |
9 | + are_valid: bool | |
10 | + | |
11 | + | |
12 | +def get_authorization_header_elements( | |
13 | + authorization_header: str, | |
14 | +) -> AuthorizationHeaderElements: | |
15 | + try: | |
16 | + authorization_scheme, bearer_token = authorization_header.split() | |
17 | + except ValueError: | |
18 | + raise BadCredentialsException | |
19 | + else: | |
20 | + valid = authorization_scheme.lower() == "bearer" and bool(bearer_token.strip()) | |
21 | + return AuthorizationHeaderElements(authorization_scheme, bearer_token, valid) | |
22 | + | |
23 | + | |
24 | +def get_bearer_token(request: StarletteRequest) -> str: | |
25 | + authorization_header = request.headers.get("Authorization") | |
26 | + if authorization_header: | |
27 | + authorization_header_elements = get_authorization_header_elements( | |
28 | + authorization_header | |
29 | + ) | |
30 | + if authorization_header_elements.are_valid: | |
31 | + return authorization_header_elements.bearer_token | |
32 | + else: | |
33 | + raise BadCredentialsException | |
34 | + else: | |
35 | + raise RequiresAuthenticationException | |
36 | + | |
37 | + | |
0 | 38 | |
▼backend/auth/expreance.py
+30-0
| @@ -0,0 +1,30 @@ | ||
1 | +from fastapi import HTTPException, status | |
2 | + | |
3 | + | |
4 | +class BadCredentialsException(HTTPException): | |
5 | + def __init__(self): | |
6 | + super().__init__( | |
7 | + status_code=status.HTTP_401_UNAUTHORIZED, detail="Bad credentials" | |
8 | + ) | |
9 | + | |
10 | + | |
11 | +class PermissionDeniedException(HTTPException): | |
12 | + def __init__(self): | |
13 | + super().__init__( | |
14 | + status_code=status.HTTP_403_FORBIDDEN, detail="Permission denied" | |
15 | + ) | |
16 | + | |
17 | + | |
18 | +class RequiresAuthenticationException(HTTPException): | |
19 | + def __init__(self): | |
20 | + super().__init__( | |
21 | + status_code=status.HTTP_401_UNAUTHORIZED, detail="Requires authentication" | |
22 | + ) | |
23 | + | |
24 | + | |
25 | +class UnableCredentialsException(HTTPException): | |
26 | + def __init__(self): | |
27 | + super().__init__( | |
28 | + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
29 | + detail="Unable to verify credentials", | |
30 | + ) | |
0 | 31 | |
▼backend/auth/json_web_token.py
+24-0
| @@ -0,0 +1,24 @@ | ||
1 | +from dataclasses import dataclass | |
2 | +import jwt | |
3 | +from matplotlib.pylab import f | |
4 | +from Gellary.backend import auth | |
5 | +from settings import setting | |
6 | +from expreance import BadCredentialsException,UnableCredentialsException | |
7 | + | |
8 | +@dataclass | |
9 | +class JsontoWebToken: | |
10 | + jwt_access_token: str | |
11 | + auth0_domain: str=f"{setting.AUTH0_DOMAIN}/" | |
12 | + auth0_audience: str=setting.AUTH0_AUDIENCE | |
13 | + algorithm: str=setting.ALGORITHM | |
14 | + jwks=f"{auth0_domain}.well-known/jwks.json" | |
15 | + | |
16 | + def verify_jwt(self): | |
17 | + try: | |
18 | + unverified_header = jwt.get_unverified_header(self.jwt_access_token) | |
19 | + except jwt.JWTError: | |
20 | + raise BadCredentialsException | |
21 | + if unverified_header["alg"] != "RS256": | |
22 | + raise UnableCredentialsException | |
23 | + return unverified_header | |
24 | + | |
0 | 25 | |
▼backend/settings/setting.py
+19-9
| @@ -1,20 +1,30 @@ | ||
1 | 1 | |
2 | +from imp import reload | |
2 | 3 | from typing import List |
3 | 4 | from decouple import config |
4 | -from pydantic import BaseSettings, AnyHttpUrl | |
5 | +from pydantic import BaseSettings, AnyHttpUrl, validator | |
5 | 6 | |
6 | 7 | class Settings(BaseSettings): |
7 | 8 | API_V1_STR: str = "/api/v1" |
8 | - SECRET_KEY: str = config('SECRET_KEY') | |
9 | - PROJECT_NAME: str = config('PROJECT_NAME') | |
10 | - BACKEND_CORS_ORIGINS: List[AnyHttpUrl] = [] | |
11 | - ALGORITHM= "HS256" | |
12 | - ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 | |
13 | - REFRESH_TOKEN_EXPIRE_MINUTES: int = 60 * 24 * 7 | |
9 | + SECRET_KEY: str | |
10 | + PROJECT_NAME: str | |
11 | + BACKEND_CORS_ORIGINS: List[AnyHttpUrl] | |
12 | + ALGORITHM:str | |
13 | + AUTH0_DOMAIN:str | |
14 | + AUTH0_AUDIENCE:str | |
15 | + CLIENT_URL:str | |
16 | + port : int | |
17 | + reload :bool | |
14 | 18 | |
15 | - | |
16 | - | |
19 | + @classmethod | |
20 | + @validator("CLIENT_URL","AUTH0_DOMAIN","AUTH0_AUDIENCE") | |
21 | + def envtest(cls, data): | |
22 | + assert data!="",f"enviroment variable {data} is not set" | |
23 | + return data | |
17 | 24 | class Config: |
25 | + env_file = ".env" | |
26 | + env_file_encoding = "utf-8" | |
18 | 27 | case_sensitive = True |
19 | 28 | |
29 | + | |
20 | 30 | settings = Settings() |
21 | 31 | |