Beispiel #1
0
def sync_lock_check(username: str, password: str, b64url: str):
    headers: Dict[str, str] = {}
    user: Optional[AuthenticatedUser] = None
    if username == "jwt":
        try:
            user = decode_jwt(password)
        except Exception:
            url = login_url(b64url, "Token non reconnu")
    else:
        try:
            user = get_auth_controller().check(username, password)
        except Exception:
            mflog.warning("exception during auth_controller.check()",
                          exc_info=True)
            url = login_url(
                b64url, "Problème lors de la vérification de l'identification")
    if user is None:
        url = login_url(b64url, "Identification non reconnue")
    else:
        url = decode_b64url_or_raise(b64url)
        jwt: str = ""
        if username == "jwt":
            jwt = password
        else:
            jwt = make_jwt(user)
        headers = {
            "Set-Cookie":
            "%s=%s; Path=/; Max-Age=%i" % (
                get_settings().cookie_name,
                jwt,
                get_settings().jwt_max_age,
            )
        }
    check_redirect_url(url)
    return RedirectResponse(url, status_code=302, headers=headers)
Beispiel #2
0
def check_redirect_url(url: str):
    parsed_url = urlparse(url)
    if parsed_url.netloc != "":
        if not parsed_url.netloc.endswith("." + get_settings().domain):
            raise HTTPException(
                400,
                "the redirection url: %s is not in the %s domain" %
                (url, get_settings().domain),
            )
Beispiel #3
0
def make_auth_backend(*args, **kwargs):
    auth_backend = get_settings().auth_backend
    if auth_backend == "ldap":
        return AuthenticationLDAPBackend(*args, **kwargs)
    elif auth_backend == "dummy":
        return AuthenticationDummyBackend(*args, **kwargs)
    raise Exception("unknown auth backend: %s" % auth_backend)
Beispiel #4
0
 def _search(self, conn, what: str) -> Optional[Tuple[str, Dict[str, Any]]]:
     result = conn.search_s(get_settings().ldap_base, ldap.SCOPE_SUBTREE,
                            what)
     try:
         return (result[0][0], result[0][1])
     except IndexError:
         return None
Beispiel #5
0
async def logout(request: Request, b64url: str = ""):
    if b64url == "":
        b64url = SLASH_B64URL
    url = decode_b64url_or_raise(b64url)
    headers: Dict[str, str] = {
        "Set-Cookie": "%s=; Path=/; Max-Age=0" % get_settings().cookie_name
    }
    check_redirect_url(url)
    return RedirectResponse(url, status_code=302, headers=headers)
Beispiel #6
0
 def check(self, username_or_email: str,
           password: str) -> Optional[AuthenticatedUser]:
     conn = ldap.initialize(get_settings().ldap_url)
     conn.set_option(ldap.OPT_REFERRALS, 0)
     conn.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
     conn.set_option(ldap.OPT_NETWORK_TIMEOUT, get_settings().ldap_timeout)
     conn.set_option(ldap.OPT_TIMEOUT, get_settings().ldap_timeout)
     if get_settings().ldap_starttls == 1:
         conn.set_option(ldap.OPT_X_TLS_CACERTFILE,
                         get_settings().ldap_cacert_file)
         conn.set_option(ldap.OPT_X_TLS, ldap.OPT_X_TLS_DEMAND)
         conn.set_option(ldap.OPT_X_TLS_DEMAND, True)
         conn.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_ALLOW)
         conn.set_option(ldap.OPT_X_TLS_NEWCTX, 0)
         conn.start_tls_s()
     if get_settings().ldap_bind_who != "":
         tmp = conn.simple_bind_s(get_settings().ldap_bind_who,
                                  get_settings().ldap_bind_pass)
         if tmp[0] != ldap.RES_BIND:
             raise Exception("bad bind code from LDAP server: %i", tmp[0])
     res: Optional[Tuple[str, Dict[str, Any]]] = self._search(
         conn, "(mail=%s)" % username_or_email)
     if res is None:
         res = self._search(conn, "(uid=%s)" % username_or_email)
         if res is None:
             return None
     try:
         tmp = conn.simple_bind_s(res[0], password)
     except Exception:
         return None
     uid_number: int = 0
     try:
         uid_number = int(res[1].get("uidNumber")[0])  # type: ignore
     except Exception:
         raise
     display_name: str = username_or_email
     if res[1].get("displayName") is not None:
         display_name = res[1].get("displayName")[0].decode(
             "utf8")  # type: ignore
     uid: str = username_or_email
     if res[1].get("uid") is not None:
         uid = res[1].get("uid")[0].decode("utf8")  # type: ignore
     mail: str = username_or_email
     if res[1].get("mail") is not None:
         mail = res[1].get("mail")[0].decode("utf8")  # type: ignore
     return AuthenticatedUser(
         username=uid,
         email=mail,
         display_name=display_name,
         uid_number=uid_number,
     )
Beispiel #7
0
def make_jwt(
    user: AuthenticatedUser,
    delta: int = -1,
    limit_to_vhosts: List[str] = [],
    limit_to_ips: List[str] = [],
) -> str:
    if delta == -1:
        delta = get_settings().jwt_max_age
    payload: Dict[str, Any] = {
        "username": user.username,
        "uid_number": user.uid_number,
        "email": user.email,
        "display_name": user.display_name,
        "iat": datetime.datetime.utcnow(),
        "exp": datetime.datetime.utcnow() + datetime.timedelta(seconds=delta),
    }
    if len(limit_to_vhosts) > 0:
        payload["limit_to_vhosts"] = limit_to_vhosts
    if len(limit_to_ips) > 0:
        payload["limit_to_ips"] = limit_to_ips
    return jwt.encode(payload, get_settings().jwt_secret, algorithm=ALGORITHM)
Beispiel #8
0
def decode_jwt(token: str) -> AuthenticatedUser:
    payload: Dict[str, Any] = jwt.decode(token,
                                         get_settings().jwt_secret,
                                         algorithms=[ALGORITHM])
    uid_number: int = 0
    try:
        uid_number = int(payload.get("uid_number"))  # type: ignore
    except Exception:
        pass
    return AuthenticatedUser(
        username=payload.get("username"),
        uid_number=uid_number,
        email=payload.get("email"),
        display_name=payload.get("display_name"),
    )
Beispiel #9
0
async def index(request: Request):
    token: Optional[str] = request.cookies.get(get_settings().cookie_name)
    user: Optional[AuthenticatedUser] = None
    if token is not None and len(token) > 0:
        try:
            user = decode_jwt(token)
        except jwt.ExpiredSignatureError:
            raise HTTPException(400, "expired token")
        except jwt.exceptions.InvalidSignatureError:
            raise HTTPException(400, "invalid token signature")
        except Exception:
            raise HTTPException(400, "can't decode token")
        if user is None:
            raise Exception("user is None (impossible)")
    context = {"request": request, "user": user, "token": token}
    return templates.TemplateResponse("index.html", context)
Beispiel #10
0
async def get_redis() -> aioredis.Redis:
    return aioredis.from_url(get_settings().redis_url)
Beispiel #11
0
from starlette.responses import JSONResponse

from repaire.api.app.auth import AuthenticationController
from repaire.api.app.settings import get_settings
from repaire.api.app.token import decode_jwt, make_jwt
from repaire.api.entities.user import AuthenticatedUser
from repaire.api.infra.auth import make_auth_backend

DIR = os.path.dirname(__file__)
SLASH_B64URL = "Lw=="

app = FastAPI()
app.mount("/static",
          StaticFiles(directory=os.path.join(DIR, "static")),
          name="static")
if get_settings().ratelimit_redis_host is not None:

    async def auth_function(scope: Any) -> Tuple[str, str]:
        try:
            return client_ip(scope)
        except Exception:
            return "default", "default"

    app.add_middleware(
        RateLimitMiddleware,
        authenticate=auth_function,
        backend=RedisBackend(
            host=get_settings().ratelimit_redis_host,
            port=get_settings().ratelimit_redis_port,
        ),
        config={