GithubHelp home page GithubHelp logo

djpugh / fastapi_aad_auth Goto Github PK

View Code? Open in Web Editor NEW
38.0 38.0 12.0 12.17 MB

Azure Active Directory Authentication wrapper for fast api

License: MIT License

Python 89.93% HTML 4.18% CSS 5.90%

fastapi_aad_auth's Introduction

Hi there ๐Ÿ‘‹

Checkout my page

fastapi_aad_auth's People

Contributors

alex-chekh avatar djpugh avatar guitared avatar oerpli avatar renovate-bot avatar renovate[bot] avatar robintw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

fastapi_aad_auth's Issues

"starlette.authentication.AuthenticationError: Unable to parse authentication token" received for user tokens generated with scope "https://graph.microsoft.com/User.Read"

I tried your library and it works fine for app tokens generated via postman with "//api/{client_id}/.default" as scope and there is no validation error. But when I generate a token using the "@azure/msal-react" library with scope "https://graph.microsoft.com/User.Read", I keep getting the unable to parse authentication token error. I also see this
"authlib.jose.errors.BadSignatureError: bad_signature:" in the logs. I used "jwt.io" to parse the token and there was no error. I added the scope to config as follows and it doesn't make any difference too.

msal_scopes = [AADConfig(scopes=['https://graph.microsoft.com/User.Read'])]
auth_provider = Authenticator(Config(providers=msal_scopes))

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/pipeline.yml
  • actions/checkout v4
  • actions/setup-python v4
  • actions/checkout v4
  • actions/setup-python v4
  • actions/checkout v4
  • actions/setup-python v4
  • actions/checkout v4
  • actions/setup-python v4
  • codecov/codecov-action v3
  • actions/checkout v4
  • actions/checkout v4
  • fossa-contrib/fossa-action v3
  • actions/checkout v4
  • github/codeql-action v2
  • github/codeql-action v2
  • actions/checkout v4
  • actions/setup-python v4
  • actions/upload-artifact v3
  • actions/checkout v4
  • actions/setup-python v4
  • actions/upload-artifact v3
  • actions/checkout v4
  • actions/setup-python v4
  • actions/download-artifact v3
  • actions/checkout v4
  • actions/setup-python v4
  • actions/download-artifact v3
  • actions/download-artifact v3
  • peaceiris/actions-gh-pages v3
.github/workflows/pr-labeler.yaml
  • TimonVS/pr-labeler-action v4
.github/workflows/release-management.yaml
  • toolmantim/release-drafter v5.25.0
pip_requirements
requirements.txt
  • jinja2 >=2.11.3
  • cryptography >=3.3.2
setup-cfg
setup.cfg

  • Check this box to trigger a request for Renovate to run again on this repository

is_valid_redirect fails with None

  File "D:\src\repos\docserver\.venv\lib\site-packages\fastapi_aad_auth\auth.py", line 157, in require_endpoint
    self._session_validator.set_post_auth_redirect(request, request.url.path)
  File "D:\src\repos\docserver\.venv\lib\site-packages\fastapi_aad_auth\_base\validators\session.py", line 44, in set_post_auth_redirect
    if not self.is_valid_redirect(redirect):
  File "D:\src\repos\docserver\.venv\lib\site-packages\fastapi_aad_auth\_base\validators\session.py", line 51, in is_valid_redirect
    return not any(map(partial(fnmatch.fnmatch, redirect), self._ignore_redirect_routes))
  File "c:\python37\lib\fnmatch.py", line 35, in fnmatch
    pat = os.path.normcase(pat)
  File "c:\python37\lib\ntpath.py", line 48, in normcase
    s = os.fspath(s)
TypeError: expected str, bytes or os.PathLike object, not NoneType

redirect = None fails in fnmatch

How to use Insomnia (or Postman) to interact with the API.

@djpugh I'm still struggling a bit how to do this whole thing without a UI... I mean I only have my API, and use Insomnia (or Postman) to interact with the API.

Could you give some pointers, as to how I should go about to actually initialize the auth flow to Azure, then use a token in the headers to be able to use the endpoints?

And as a bonus, does this module provide a callback, so that the user model could be persisted in the DB?

Originally posted by @soderluk in #16 (comment)

'Invalid key set format' error when logging in

I have previously deployed fastapi_aad_auth successfully in an Azure Functions app. I'm now trying to replicate this in a second Azure Functions app, and am running into an error.

When I go to the /login endpoint, I get the standard dialogs to login, but then I get a 500 error. The full trace is below (sorry for the poor formatting, Azure provides the logs from Azure Functions in a strange format and I had to try and tidy it up myself) - the main error is an Invalid key set format error.

Do you have any idea what's going on here? I'm pretty sure I've set up the app in the same way as my first app (which works fine).

Exception: ValueError: Invalid key set format
Stack:

File "/azure-functions-host/workers/python/3.8/LINUX/X64/azure_functions_worker/dispatcher.py", line 402, in _handle__invocation_request
call_result = await self._loop.run_in_executor(
    
File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run
        result = self.fn(*self.args, **self.kwargs)
    
File "/azure-functions-host/workers/python/3.8/LINUX/X64/azure_functions_worker/dispatcher.py", line 611, in _run_sync_func
        return ExtensionManager.get_sync_invocation_wrapper(context,
File "/azure-functions-host/workers/python/3.8/LINUX/X64/azure_functions_worker/extension.py", line 215, in _raw_invocation_wrapperresult = function(**args)
File "/home/site/wwwroot/HttpTrigger1/__init__.py", line 172, in mainreturn AsgiMiddleware(app).handle(req, context)
File "/home/site/wwwroot/HttpTrigger1/__init__.py", line 154, in handlereturn self._handle(req, context)
File "/home/site/wwwroot/HttpTrigger1/__init__.py", line 161, in _handleasgi_response = self._loop.run_until_complete(
File "/usr/local/lib/python3.8/asyncio/base_events.py", line 616, in run_until_completereturn future.result()
File "/home/site/wwwroot/HttpTrigger1/__init__.py", line 71, in from_appawait app(scope, res._receive, res._send)
File "/home/site/wwwroot/.python_packages/lib/site-packages/fastapi/applications.py", line 208, in __call__await super().__call__(scope, receive, send)
File "/home/site/wwwroot/.python_packages/lib/site-packages/starlette/applications.py", line 112, in __call__await self.middleware_stack(scope, receive, send)
File "/home/site/wwwroot/.python_packages/lib/site-packages/starlette/middleware/errors.py", line 181, in __call__raise exc
File "/home/site/wwwroot/.python_packages/lib/site-packages/starlette/middleware/errors.py", line 159, in __call__await self.app(scope, receive, _send)
File "/home/site/wwwroot/.python_packages/lib/site-packages/starlette/middleware/sessions.py", line 77, in __call__await self.app(scope, receive, send_wrapper)
File "/home/site/wwwroot/.python_packages/lib/site-packages/starlette/middleware/authentication.py", line 48, in __call__await self.app(scope, receive, send)
File "/home/site/wwwroot/.python_packages/lib/site-packages/starlette/middleware/cors.py", line 84, in __call__await self.app(scope, receive, send)
File "/home/site/wwwroot/.python_packages/lib/site-packages/starlette/exceptions.py", line 82, in __call__raise exc
File "/home/site/wwwroot/.python_packages/lib/site-packages/starlette/exceptions.py", line 71, in __call__await self.app(scope, receive, sender)
File "/home/site/wwwroot/.python_packages/lib/site-packages/starlette/routing.py", line 589, in __call__await route.handle(scope, receive, send)
File "/home/site/wwwroot/.python_packages/lib/site-packages/starlette/routing.py", line 250, in handleawait self.app(scope, receive, send)
File "/home/site/wwwroot/.python_packages/lib/site-packages/starlette/routing.py", line 52, in appresponse = await func(request)
File "/home/site/wwwroot/.python_packages/lib/site-packages/fastapi_aad_auth/_base/provider.py", line 44, in login_callback
    return self.authenticator.process_login_callback(request)
File "/home/site/wwwroot/.python_packages/lib/site-packages/fastapi_aad_auth/_base/authenticators/session.py", line 66, in process_login_callback
    user = self._get_user_from_token(token)
File "/home/site/wwwroot/.python_packages/lib/site-packages/fastapi_aad_auth/providers/aad.py", line 109, in _get_user_from_token
    return super()._get_user_from_token(token, options=options)
File "/home/site/wwwroot/.python_packages/lib/site-packages/fastapi_aad_auth/_base/authenticators/session.py", line 91, in _get_user_from_token
    validated_claims = self._token_validator.validate_token(token, options=options)
File "/home/site/wwwroot/.python_packages/lib/site-packages/fastapi_aad_auth/_base/validators/token.py", line 120, in validate_token
    claims = self._decode_token(token)
File "/home/site/wwwroot/.python_packages/lib/site-packages/fastapi_aad_auth/providers/aad.py", line 194, in _decode_token
    jwk_ = self._get_ms_jwk(token)
File "/home/site/wwwroot/.python_packages/lib/site-packages/fastapi_aad_auth/providers/aad.py", line 188, in _get_ms_jwk
    return jwk.loads(key)
File "/home/site/wwwroot/.python_packages/lib/site-packages/authlib/jose/jwk.py", line 6, in loads
    key_set = JsonWebKey.import_key_set(obj)
File "/home/site/wwwroot/.python_packages/lib/site-packages/authlib/jose/rfc7517/jwk.py", line 55, in import_key_set
    raise ValueError('Invalid key set format')

AADTokenValidator caching?

Is it possible to get some caching around _get_ms_jwk? It requests that key_url endpoint per login which can add up when not using sessions. Guess it would be safe to cache the result for maybe 60s or something?

Secure my api from openid token

I didn't get much from the doc to secure an API with azure openid token. Lets say my web/mobile client is sending Bearer token in header and I want my api to be secured e.g.

app = FastAPI()

app.config['AZURE_OAUTH_TENANCY'] = 'xxx'
app.config['AZURE_OAUTH_APPLICATION_ID'] = 'xxx'

auth = Authenticator()
auth.init_app(app)

@app.route('/unprotected')
def unprotected():
return 'hello world'

@app.route('/protected')
@auth()
def protected():
return 'hello authenticated entity'

@app.route('/protected-with-single-scope')
@auth('required-scope')
def protected_with_scope():
return 'hello authenticated and authorised entity'

@app.route('/protected-with-multiple-scopes')
@auth('required-scope1 required-scope2')
def protected_with_multiple_scopes():
return 'hello authenticated and authorised entity'

I'm looking for some declarative like @auth or some kind of configuration which will secure my /helllo api at backend.

[Feature request] Add py.typed marker

This package has type hints, but none of them are available to codebases using this package as the py.typed marker is not present. All you need to do is add an empty file called py.typed and all library users can enjoy the benefits of seeing the type hints inside the library. You may also need to update the setup.cfg to ensure the py.typed file is included in the package bundle.

See: https://peps.python.org/pep-0561/#packaging-type-information

Implicit flow ? Scopes ?

Hello !

Is there a way to configure OpenApi to use Implicit flow ?

I need to be able to authenticate my through the OpenAPI ("/doc") interface, using the "implicit" flow:
image

Today, I'm constraint to use the "authorization code" strategy (where I need to provide client id / secret)

image

Other question, using the authorization code, I did not find a way to specify the scope ?
Where should I register my API scope ?

(Great work on this tool, love it :) )

UPDATE

Using only FastAPI, I'm able to prefill scopes and set the authentication from OpenApi, to Implicit flow, using this code

scopes = {
    "https://..../user_impersonation": "https://..../user_impersonation",
}
oauth2_scheme = OAuth2(
    flows=OAuthFlows(
        implicit=OAuthFlowImplicit(
            authorizationUrl="https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
            scopes=scopes,
        )
    )
)

@app.get("/hello")
async def hello_world(token: str = Depends(oauth2_scheme)):
    print(token)
    return {"hello": "world"}

The idea is to know how to do the same, using your great api ?

Restrict login to users with a specific role

I'm trying to restrict the users allowed to login to my application to just those who have a specific role set.

I have set my roles up in the Azure Portal, and the role (Data) is defined in the manifest for my app. If I add or remove that role to my user, then I can see it is correctly listed (or not listed) in the /me endpoint once I've logged in.

I have tried to set the AAD_ROLES variable in my .env file to list the role that I want all users to have. I've specified it like this:

AAD_ROLES="[\"Data\"]"

However, I still find that I am able to login even when I haven't been assigned that role.

Is this the correct way to require a specific role when logging in? Have I specified the role correctly in the AAD_ROLES env var? (I tried various ways, and most of them gave JSON errors, but this doesn't seem to give an error)

Any help would be much appreciated.

Fix 0.1.3 Release

#16 needs releasing - there was an error in the tags that is affecting the build

msal.PublicClientApplication not working

I am not sure whether this actually is an issue with this library. If it is not I hope someone here might know the issue.

I am trying to setup a public client application for internal use, using our aad. Authorization using the /docs page works fine, however a sign-in using the msal.PublicClientApplication fails wit the following:

2021-06-01 12:08:58,760 - 918bd735a7944622ac7d2ba14c50629c - AADTokenValidator - DEBUG - Processed Key: b'-----BEGIN RSA PUBLIC KEY-----\nMIIBC...IDAQAB\n-----END RSA PUBLIC KEY-----\n'
2021-06-01 12:08:58,760 - 918bd735a7944622ac7d2ba14c50629c - AADTokenValidator - ERROR - Unable to parse error
Traceback (most recent call last):
  File "python3.9/site-packages/fastapi_aad_auth/providers/aad.py", line 202, in _decode_token
    claims = jwt.decode(
  File "python3.9/site-packages/authlib/jose/rfc7519/jwt.py", line 99, in decode
    data = self._jws.deserialize_compact(s, load_key, decode_payload)
  File "python3.9/site-packages/authlib/jose/rfc7515/jws.py", line 105, in deserialize_compact
    raise BadSignatureError(rv)
authlib.jose.errors.BadSignatureError: bad_signature: 
2021-06-01 12:08:58,760 - 918bd735a7944622ac7d2ba14c50629c - AADTokenValidator - ERROR - Error authenticating via token
Traceback (most recent call last):
  File "python3.9/site-packages/fastapi_aad_auth/providers/aad.py", line 202, in _decode_token
    claims = jwt.decode(
  File "python3.9/site-packages/authlib/jose/rfc7519/jwt.py", line 99, in decode
    data = self._jws.deserialize_compact(s, load_key, decode_payload)
  File "python3.9/site-packages/authlib/jose/rfc7515/jws.py", line 105, in deserialize_compact
    raise BadSignatureError(rv)
authlib.jose.errors.BadSignatureError: bad_signature: 

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "python3.9/site-packages/fastapi_aad_auth/_base/validators/token.py", line 52, in check
    claims = self.validate_token(token)
  File "python3.9/site-packages/fastapi_aad_auth/_base/validators/token.py", line 109, in validate_token
    claims = self._decode_token(token)
  File "python3.9/site-packages/fastapi_aad_auth/providers/aad.py", line 208, in _decode_token
    raise AuthenticationError("Unable to parse authentication token")
starlette.authentication.AuthenticationError: Unable to parse authentication token

I have verified the arguments to jwt.decode(token, key) and both are set, I did notice the token is much longer than when used through the /docs endpoint.

To replicate this, the client looks like:

import msal
from pprint import pprint
import requests

client_id = ''
tenant_id = ''

if __name__ == '__main__':
    client = msal.PublicClientApplication(
        client_id=client_id,
        authority=f'https://login.microsoftonline.com/{tenant_id}'
    )
    response = client.acquire_token_interactive([client_id])
    pprint(response)

    try:
        token = response['access_token']
    except KeyError:
        pprint(response)
    else:
        user_response = requests.get('https://graph.microsoft.com/v1.0/me', headers={
            'Authorization': f'Bearer {token}'
        })
        pprint(user_response.json())

        my_api_response = requests.get('http://localhost:8000/customers', headers={
            'Authorization': f'Bearer {token}'
        })
        pprint(my_api_response.json())

The "graph" endpoint works and I can see the signed in user. My_api however doesn't and produces the error above.

In AAD I have added under "Authentication"->"Mobile and Desktop Applications" the callback url "http://localhost".
Further is ofcourse the "Allow public client flows" option set to Yes.

Could this be an issue with the way this library processes the token or is something else wrong?

/login page broken after upgrading to fastapi 0.70.0

The login page templating seems to be broken with fastapi 0.70.0/Starlette 0.16.0.

2021-10-12 13:33:08,118 - uvicorn.access - INFO - 127.0.0.1:59355 - "GET /login HTTP/1.1" 500
2021-10-12 13:33:08,119 - uvicorn.error - ERROR - Exception in ASGI application
Traceback (most recent call last):
  File "/path/python3.9/site-packages/uvicorn/protocols/http/httptools_impl.py", line 375, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "/path/python3.9/site-packages/uvicorn/middleware/proxy_headers.py", line 75, in __call__
    return await self.app(scope, receive, send)
  File "/path/python3.9/site-packages/fastapi/applications.py", line 208, in __call__
    await super().__call__(scope, receive, send)
  File "/path/python3.9/site-packages/starlette/applications.py", line 112, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/path/python3.9/site-packages/starlette/middleware/errors.py", line 181, in __call__
    raise exc
  File "/path/python3.9/site-packages/starlette/middleware/errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "/path/python3.9/site-packages/starlette/middleware/sessions.py", line 77, in __call__
    await self.app(scope, receive, send_wrapper)
  File "/path/python3.9/site-packages/starlette/middleware/authentication.py", line 48, in __call__
    await self.app(scope, receive, send)
  File "/path/python3.9/site-packages/starlette_context/middleware/raw_middleware.py", line 96, in __call__
    await self.app(scope, receive, send_wrapper)
  File "/path/python3.9/site-packages/starlette/middleware/cors.py", line 84, in __call__
    await self.app(scope, receive, send)
  File "/path/python3.9/site-packages/starlette/exceptions.py", line 82, in __call__
    raise exc
  File "/path/python3.9/site-packages/starlette/exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "/path/python3.9/site-packages/starlette/routing.py", line 656, in __call__
    await route.handle(scope, receive, send)
  File "/path/python3.9/site-packages/starlette/routing.py", line 259, in handle
    await self.app(scope, receive, send)
  File "/path/python3.9/site-packages/starlette/routing.py", line 61, in app
    response = await func(request)
  File "/path/python3.9/site-packages/fastapi_aad_auth/ui/__init__.py", line 123, in login
    return self._login(request)
  File "/path/python3.9/site-packages/fastapi_aad_auth/ui/__init__.py", line 64, in _login
    return self.login_templates.TemplateResponse(self.login_template_path.name, context)  # type: ignore
  File "/path/python3.9/site-packages/starlette/templating.py", line 87, in TemplateResponse
    return _TemplateResponse(
  File "/path/python3.9/site-packages/starlette/templating.py", line 33, in __init__
    content = template.render(context)
  File "/path/python3.9/site-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/path/python3.9/site-packages/jinja2/environment.py", line 925, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "/path/python3.9/site-packages/fastapi_aad_auth/ui/login.html", line 1, in top-level template code
    {% extends "fastapi_aad_auth.ui:base.html" %}
  File "/path/python3.9/site-packages/jinja2/loaders.py", line 214, in get_source
    raise TemplateNotFound(template)
jinja2.exceptions.TemplateNotFound: fastapi_aad_auth.ui:base.html

Session states do not match exception

I've run into a strange problem where I'm suddenly getting a Session states do not match error when trying to login in my app using fastapi_aad_auth. Everything was working fine and then I suddenly started getting this error, and I'm pretty sure I haven't changed anything.

I can see that the error is raised from state.py, line 91:

raise AuthenticationError("Session states do not match")

Are you able to provide any information on why there might be a mismatch in session states occurring here? I've tried this on two different computers with two different AAD logins, and it is occurring in both situations. I've tried running locally and it is working fine, so I'm only running into the error on the version that is hosted on Azure. I've tried restarting the Azure Functions app, and that hasn't solved it.

Also, on a different note: my boss has just pointed out that I'm working for the same company as you! I'm working with Sam Murphy.

Question: How to protect API routes without UI login

First of all, thanks for your work on the library!

I'm struggling a bit trying to understand the usage of the library though.

How does one protect an API route without the need to have any UI?
I'm reading the docs, but cannot for the life of me figure out how to use this for a plain API.

The authentication works well when using the /docs endpoint, but e.g. using insomnia and reading endpoints, I just can't get the authentication to work.

Having the dependency in the route auth_state: AuthenticationState = Depends(auth_provider.api_auth_scheme) shows the auth_state as None.

In my main.py I use

auth_provider = AADAuth()
app = FastAPI(
        title=PROJECT_TITLE,
        debug=DEBUG,
        version=VERSION,
        swagger_ui_init_oauth=auth_provider.api_auth_scheme.init_oauth,
    )
auth_provider.configure_app(app)

in my routes:

@router.get("/", response_model=List[schemas.Model])
async def list_models(
    skip: int = 0,
    limit: int = 100,
    auth_state: AuthenticationState = Depends(auth_provider.api_auth_scheme),
):
    stored = await domain.Model.find_all(skip, limit)
    models = [schemas.Model(**model) for model in stored]
    return JSONResponse(content=jsonable_encoder(models))

Any help appreciated!

jinja2.exceptions.TemplateNotFound: fastapi_aad_auth.ui:base.html

Hello, i try use your library, but i get some problems

I wrote

import uvicorn
from fastapi import FastAPI, Request, Response, Depends
from starlette.middleware.sessions import SessionMiddleware
import os
from fastapi_sqlalchemy import DBSessionMiddleware
from fastapi_sqlalchemy import db
from models import User as ModelUser
from schema import User as SchemaUser
from dotenv import load_dotenv

from fastapi_aad_auth import AuthenticationState, Config, auth, Authenticator
from fastapi_aad_auth.providers.aad import AADConfig

auth_provider = auth.AADAuth()

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
load_dotenv(os.path.join(BASE_DIR, ".env"))

app = FastAPI()

auth_provider.configure_app(app)
app.add_middleware(DBSessionMiddleware, db_url=os.environ["DATABASE_URL"])
app.add_middleware(SessionMiddleware, secret_key="example")

@app.post("/user/", response_model=SchemaUser)
def create_user(user: SchemaUser):
    db_user = ModelUser(
        first_name=user.first_name, last_name=user.last_name, age=user.age
    )
    db.session.add(db_user)
    db.session.commit()
    return db_user

@app.get("/")
def index(auth_state: AuthenticationState = Depends(auth_provider.auth_backend.requires_auth(allow_session=True))):
    print(auth_state)
    return {'hello': 'world'}


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

But when i try to load 127.0.0.1:8000/docs, i get an error

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 366, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 75, in __call__
    return await self.app(scope, receive, send)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\fastapi\applications.py", line 261, in __call__
    await super().__call__(scope, receive, send)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\applications.py", line 112, in __call__
    await self.middleware_stack(scope, receive, send)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
    raise exc
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\middleware\base.py", line 63, in __call__
    response = await self.dispatch_func(request, call_next)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\fastapi_sqlalchemy\middleware.py", line 44, in dispatch
    response = await call_next(request)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\middleware\base.py", line 44, in call_next
    raise app_exc
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\middleware\base.py", line 34, in coro
    await self.app(scope, request.receive, send_stream.send)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\middleware\sessions.py", line 77, in __call__
    await self.app(scope, receive, send_wrapper)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\middleware\authentication.py", line 48, in __call__
    await self.app(scope, receive, send)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\exceptions.py", line 82, in __call__
    raise exc
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 21, in __call__
    raise e
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 18, in __call__
    await self.app(scope, receive, send)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\routing.py", line 656, in __call__
    await route.handle(scope, receive, send)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\routing.py", line 259, in handle
    await self.app(scope, receive, send)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\routing.py", line 61, in app
    response = await func(request)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\fastapi_aad_auth\ui\__init__.py", line 123, in login
    return self._login(request)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\fastapi_aad_auth\ui\__init__.py", line 64, in _login
    return self.login_templates.TemplateResponse(self.login_template_path.name, context)  # type: ignore
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\templating.py", line 90, in TemplateResponse
    return _TemplateResponse(
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\starlette\templating.py", line 34, in __init__
    content = template.render(context)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\jinja2\environment.py", line 1291, in render
    self.environment.handle_exception()
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\jinja2\environment.py", line 926, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\fastapi_aad_auth\ui\login.html", line 1, in top-level template code
    {% extends "fastapi_aad_auth.ui:base.html" %}
  File "C:\Users\andrey\.virtualenvs\backend-9dmwlUHU\lib\site-packages\jinja2\loaders.py", line 218, in get_source
    raise TemplateNotFound(template)
jinja2.exceptions.TemplateNotFound: fastapi_aad_auth.ui:base.html```

KeyError: 'fastapi_aad_auth\\ui\\login.html' when trying to run tests/testapp/server.py with .env

@djpugh I have cloned master branch and ran setup.py install, then i am trying to run tests/testapp/server.py with .env that has AAD_CLIENT_ID,AAD_TENANT_ID and AAD_CLIENT_SECRET

(my-env) PS C:\Users\user1\Downloads\fastapi_aad_auth-master\fastapi_aad_auth-master> uvicorn --host=0.0.0.0 tests.testapp.server:app --reload
?[32mINFO?[0m: Uvicorn running on ?[1mhttp://0.0.0.0:8000?[0m (Press CTRL+C to quit)
?[32mINFO?[0m: Started reloader process [?[36m?[1m24616?[0m] using ?[36m?[1mstatreload?[0m
Process SpawnProcess-1:
Traceback (most recent call last):
File "C:\Users\user1\Anaconda\lib\multiprocessing\process.py", line 258, in _bootstrap
self.run()
File "C:\Users\user1\Anaconda\lib\multiprocessing\process.py", line 93, in run
self._target(*self._args, **self.kwargs)
File "C:\Users\user1\downloads\fastapi_aad_auth-master\fastapi_aad_auth-master\my-env\lib\site-packages\uvicorn\subprocess.py", line 62, in subprocess_started
target(sockets=sockets)
File "C:\Users\user1\downloads\fastapi_aad_auth-master\fastapi_aad_auth-master\my-env\lib\site-packages\uvicorn\main.py", line 390, in run
loop.run_until_complete(self.serve(sockets=sockets))
File "C:\Users\user1\Anaconda\lib\asyncio\base_events.py", line 484, in run_until_complete
return future.result()
File "C:\Users\user1\downloads\fastapi_aad_auth-master\fastapi_aad_auth-master\my-env\lib\site-packages\uvicorn\main.py", line 397, in serve
config.load()
File "C:\Users\user1\downloads\fastapi_aad_auth-master\fastapi_aad_auth-master\my-env\lib\site-packages\uvicorn\config.py", line 278, in load
self.loaded_app = import_from_string(self.app)
File "C:\Users\user1\downloads\fastapi_aad_auth-master\fastapi_aad_auth-master\my-env\lib\site-packages\uvicorn\importer.py", line 20, in import_from_string
module = importlib.import_module(module_str)
File "C:\Users\user1\Anaconda\lib\importlib_init
.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "", line 994, in _gcd_import
File "", line 971, in _find_and_load
File "", line 955, in _find_and_load_unlocked
File "", line 665, in _load_unlocked
File "", line 678, in exec_module
File "", line 219, in _call_with_frames_removed
File ".\tests\testapp\server.py", line 11, in
from fastapi_aad_auth import AADAuth, AuthenticationState, Config
File "", line 971, in _find_and_load
File "", line 955, in _find_and_load_unlocked
File "", line 656, in _load_unlocked
File "", line 626, in load_backward_compatible
File "C:\Users\user1\downloads\fastapi_aad_auth-master\fastapi_aad_auth-master\my-env\lib\site-packages\fastapi_aad_auth-0.0.1-py3.6.egg\fastapi_aad_auth_init
.py", line 1, in
from fastapi_aad_auth.auth import AADAuth # noqa F401
File "", line 971, in _find_and_load
File "", line 955, in _find_and_load_unlocked
File "", line 656, in _load_unlocked
File "", line 626, in _load_backward_compatible
File "C:\Users\user1\downloads\fastapi_aad_auth-master\fastapi_aad_auth-master\my-env\lib\site-packages\fastapi_aad_auth-0.0.1-py3.6.egg\fastapi_aad_auth\auth.py", line 14, in
from fastapi_aad_auth.config import Config
File "", line 971, in _find_and_load
File "", line 955, in _find_and_load_unlocked
File "", line 656, in load_unlocked
File "", line 626, in load_backward_compatible
File "C:\Users\user1\downloads\fastapi_aad_auth-master\fastapi_aad_auth-master\my-env\lib\site-packages\fastapi_aad_auth-0.0.1-py3.6.egg\fastapi_aad_auth\config.py", line 36, in
class LoginUIConfig(BaseSettings):
File "C:\Users\user1\downloads\fastapi_aad_auth-master\fastapi_aad_auth-master\my-env\lib\site-packages\fastapi_aad_auth-0.0.1-py3.6.egg\fastapi_aad_auth\config.py", line 38, in LoginUIConfig
template_file: FilePath = Field(resource_filename('fastapi_aad_auth.ui', 'login.html'), env='FASTAPI_AUTH_LOGIN_TEMPLATE_FILE')
File "C:\Users\user1\downloads\fastapi_aad_auth-master\fastapi_aad_auth-master\my-env\lib\site-packages\pkg_resources_init
.py", line 1143, in resource_filename
self, resource_name
File "C:\Users\user1\downloads\fastapi_aad_auth-master\fastapi_aad_auth-master\my-env\lib\site-packages\pkg_resources_init
.py", line 1650, in get_resource_filename
return self.extract_resource(manager, zip_path)
File "C:\Users\user1\downloads\fastapi_aad_auth-master\fastapi_aad_auth-master\my-env\lib\site-packages\pkg_resources_init
.py", line 1671, in _extract_resource
timestamp, size = self._get_date_and_size(self.zipinfo[zip_path])
KeyError: 'fastapi_aad_auth\ui\login.html'

It will be also great help if you can share any articles that you published for using this package

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.