async def login( ws_access_token: bool = False, db: Session = Depends(session), form: OAuth2PasswordRequestForm = Depends(), ): user = db.query(User).filter_by(email=form.username).first() if not user or not user.hashed_password: logger.warning(f"user exists failed for {form.username}") raise HTTPException(status_code=401, detail="Incorrect email or password") if not verify_password(form.password, user.hashed_password): logger.warning(f"hash verification failed for {form.username}") raise HTTPException(status_code=401, detail="Incorrect email or password") if user.mfa_secret: # mfa is enabled scopes = "profile mfa_required" elif user.is_superuser: scopes = "profile super zone user dns-request api-token refresh dns-record dns-server" # grant access to super routes else: scopes = "profile zone user:list dns-request api-token:list api-token:create api-token:destroy refresh dns-record:list dns-record:show dns-server:list dns-server:show" logger.warning(f"creating token with scopes {scopes}") token = create_bearer_token(data={"sub": user.id, "scopes": scopes}) data = {"token_type": "bearer", "access_token": str(token.decode())} if ws_access_token: data["ws_access_token"] = create_bearer_token( data={ "sub": user.id, "scopes": "zone:publish dns-request:publish refresh" }) return PasswordAuthResponse(**data)
def bearer_token(dns_server_name, scopes): return str( create_bearer_token(data={ "sub": 1, "dns_server_name": dns_server_name, "scopes": scopes }).decode())
async def login(token: TokenPayload = ScopedTo("refresh"), user: User = Depends(current_user)): token = create_bearer_token(data={ "sub": token.sub, "scopes": " ".join(token.scopes) }) return PasswordAuthResponse(token_type="bearer", access_token=str(token.decode()))
async def login( ws_access_token: bool = False, db: Session = Depends(async_session), form: OAuth2PasswordRequestForm = Depends(), ): username = form.username.lower() if form.username else "" user = db.query(User).filter_by(email=username).first() if not user or not user.hashed_password: logger.warning(f"user exists failed for {username}") raise HTTPException(status_code=401, detail="Incorrect email or password") if not verify_password(form.password, user.hashed_password): logger.warning(f"hash verification failed for {username}") raise HTTPException(status_code=401, detail="Incorrect email or password") if user.mfa_secret: # mfa is enabled scopes = "profile mfa_required" elif user.is_superuser: scopes = SUPER_SCOPES # grant access to super routes else: scopes = NORMAL_SCOPES logger.warning(f"creating token with scopes {scopes}") token = create_bearer_token(data={"sub": user.id, "scopes": scopes}) data = {"token_type": "bearer", "access_token": str(token)} if ws_access_token and int(environ.get("BROADCAST_ENABLED", 0)) == 1: # TODO: make it so that you cannot get publish access without base scope data["ws_access_token"] = create_bearer_token(data={ "sub": user.id, "scopes": PUBLISH_SCOPES }) return PasswordAuthResponse(**data)
def test_username_is_not_valid_email_format_causes_failure(client, session): auth = factory("SuperUserFactory", session=session).create() token = create_bearer_token(data={"sub": auth.id, "scopes": SUPER_SCOPES}) bearer = "Bearer " + str(token) data = { "email": "testtest", "password": "******", "password_confirm": "Password123", } response = client.post( "/api/v1/user", json=data, headers={ "Content-Type": "application/json", "Authorization": bearer }, ) assert response.status_code == 422
def test_regular_user_cannot_create_user(client, session): auth = factory("UserFactory", session=session).create() token = create_bearer_token(data={"sub": auth.id, "scopes": NORMAL_SCOPES}) bearer = "Bearer " + str(token) data = { "email": "*****@*****.**", "password": "******", "password_confirm": "Password123", } response = client.post( "/api/v1/user", json=data, headers={ "Content-Type": "application/json", "Authorization": bearer }, ) assert response.status_code == 403
async def run(self): self.load_env("api") self.db_register() dns_server_name = self.option("dns_server_name", None) or uuid.uuid4().hex scopes = self.get_scopes() expires_delta = timedelta(days=self.option("days")) expires_at = datetime.utcnow() + expires_delta token = create_bearer_token( data={ "sub": self.option("user_id"), "scopes": scopes, "dns_server_name": dns_server_name, }, expire=expires_at, ) print("API_TOKEN:{}".format(str(token.decode())))
async def store( form: ApiTokenCreateForm, api_token_repo: ApiTokenRepo = Depends(ApiTokenRepo()), dns_server_repo: DnsServerRepo = Depends(DnsServerRepo()), token: TokenPayload = Depends(ScopedTo("api-token:create")), user: User = Depends(current_user), ): dns_server = dns_server_repo.first_or_fail(id=form.dns_server_id).results() scopes = [] for requested_scope in form.scopes.split(" "): request_scope_satisfied = False for user_token in token.scopes: # TODO: double check this, pretty lenient # if a:b in a:b:c if user_token in requested_scope: request_scope_satisfied = True if not request_scope_satisfied: logger.warning( f"[email protected]: Attempt to create unauthorized scope {requested_scope}" ) raise HTTPException(403, detail="unauthorized") else: scopes.append(requested_scope) # TODO: use better randomness token = create_bearer_token( data={ "sub": user.id, "scopes": " ".join(scopes), "dns_server_name": dns_server.name, }) data = { "scopes": " ".join(scopes), "token": str(token), "expires_at": form.expires_at, "dns_server_id": form.dns_server_id, } api_token = api_token_repo.create(data).data() return ApiTokenResponse(api_token=api_token)
async def login(db: Session = Depends(session), form: OAuth2PasswordRequestForm = Depends()): user = db.query(User).filter_by(email=form.username).first() if not user or not user.hashed_password: raise HTTPException(status_code=400, detail="Incorrect email or password") if not verify_password(form.password, user.hashed_password): raise HTTPException(status_code=400, detail="Incorrect email or password") if user.mfa_secret: # mfa is enabled scopes = "profile mfa_required" elif user.is_superuser: scopes = "profile super zone user" # grant access to super routes else: scopes = "profile zone user:list" token = create_bearer_token(data={"sub": user.id, "scopes": scopes}) return PasswordAuthResponse(token_type="bearer", access_token=str(token.decode()))
def test_superuser_can_update_user(client, session): auth = factory("SuperUserFactory", session=session).create() target = factory("UserFactory", session=session).create(email="*****@*****.**") token = create_bearer_token(data={"sub": auth.id, "scopes": SUPER_SCOPES}) bearer = "Bearer " + str(token) data = {"email": "*****@*****.**"} response = client.put( f"/api/v1/user/{str(target.id)}", json=data, headers={ "Content-Type": "application/json", "Authorization": bearer }, ) assert response.status_code == 200 assert response.json()["user"]["email"] == data["email"]
def test_email_must_not_already_exist_or_failure(client, session): auth = factory("SuperUserFactory", session=session).create() existing = factory("UserFactory", session=session).create(email="*****@*****.**") target = factory("UserFactory", session=session).create(email="*****@*****.**") token = create_bearer_token(data={"sub": auth.id, "scopes": SUPER_SCOPES}) bearer = "Bearer " + str(token) data = {"email": existing.email} response = client.put( f"/api/v1/user/{str(target.id)}", json=data, headers={ "Content-Type": "application/json", "Authorization": bearer }, ) assert response.status_code == 422