Package: imia
ImiaImia (belarussian for "a name") is an authentication library for Starlette and FastAPI (python 3.8+).Production statusThe library is considered in "beta" state thus may contain bugs or security issues, but I actively use it in production.InstallationInstallimiausing PIP or poetry:pipinstallimia# orpoetryaddimiaFeaturesLogin/logout flowsPluggable authenticators:WWW-Basicsessiontokenbearer tokenany token (customizable)API keyDatabase agnostic user storageAuthentication middlewarewith fallback strategies:redirect to an URLraise an exceptiondo nothingwith optional URL protectionwith option URL exclusion from protectionUser Impersonation (stateless and stateful)SQLAlchemy 1.4 (async mode) integrationTODOremember meA very quick startIf you are too lazy to read this doc, take a look intoexamples/directory. There you will find several files demoing
various parts of this library.How it works?Here are all moving parts:UserLikeobject, aka "user model" - is an arbitrary class that implementsimia.UserLikeprotocol.a user provider- an adapter that loads user model (UserLike object) from the storage (a database).an authenticator- a class that loads user using the user provider from the request (eg. session)an authentication middlewarethat accepts an HTTP request and calls authenticators for a user model. The
middleware always populatesrequest.authwithUserToken.user tokenis a class that holds authentication stateWhen a HTTP request reaches your application, animia.AuthenticationMiddlewarewill start handling it. The middleware
iterates over configured authenticators and stops on the first one that returns non-None value. At this point the
request is considered authenticated. If no authenticators return user model then the middleware will createanonymous
user token. The user token available inrequest.authproperty. Useuser_token.is_authenticatedtoken property to
make sure that user is authenticated.User authentication quick startCreate a user model and implement methods defined byimia.UserLikeprotocol.Create an instance ofimia.UserProviderthat corresponds to your user storage. Feel free to create your own.Setup one or more authenticators and pass them to the middlewareAddimia.AuthenticationMiddlewareto your Starlette applicationAt this point you are done.Here is a brief example that uses in-memory provider for demo purpose. For production environment you should use
database backed providers likeSQLAlchemyORMUserProviderorSQLAlchemyCoreUserProvider. Also, for simplicity reason
we will not implementlogin/logout flowand will authenticate requests using API keys.fromdataclassesimportdataclass,fieldfromstarlette.applicationsimportStarlettefromstarlette.middlewareimportMiddlewarefromstarlette.requestsimportRequestfromstarlette.responsesimportJSONResponsefromstarlette.routingimportRoutefromimiaimportAPIKeyAuthenticator,AuthenticationMiddleware,InMemoryProvider@dataclassclassUser:"""This is our user model. It may be an ORM model, or any python class, the library does not care of it,it only expects that the class has methods defined by the UserLike protocol."""id:strpassword:str='password'scopes:list[str]=field(default_factory=list)defget_display_name(self)->str:returnself.id.split('@')[0].title()defget_id(self)->str:returnself.iddefget_hashed_password(self)->str:returnself.passworddefget_scopes(self)->list:returnself.scopesasyncdefwhoami_view(request:Request)->JSONResponse:returnJSONResponse({'id':request.auth.user_id,'name':request.auth.display_name,})user_provider=InMemoryProvider({'user1@example.com':User(id='user1@example.com'),'user2@example.com':User(id='user2@example.com'),})authenticators=[APIKeyAuthenticator(user_provider=user_provider),]routes=[Route('/',whoami_view),]middleware=[Middleware(AuthenticationMiddleware,authenticators=authenticators)]app=Starlette(routes=routes,middleware=middleware)Now save the file tomyapp.pyand run it withuvicornapplication server:uvicornmyapp:appOpenhttp://127.0.0.1:8000/and see that your request is not authenticated and user is anonymous. Let's pass API key
via query parameters to make the configured APIKeyAuthenticator to load user. This time
openhttp://127.0.0.1:8000/?apikey=user1@example.comin your browser. Now the request is fully authenticated as User1
user.For more details refer to the doc sections below.DocsUserLike protocol (a user model)Load user from databases using User ProvidersRequest authenticationBuilt-in authenticatorsUser tokenPasswordsLogin/Logout flowUser impersontationUsageSeeexamples/directory.