Authentication
Starlette offers a simple but powerful interface for handling authenticationand permissions. Once you've installedAuthenticationMiddleware with anappropriate authentication backend therequest.user andrequest.authinterfaces will be available in your endpoints.
fromstarlette.applicationsimportStarlettefromstarlette.authenticationimport(AuthCredentials,AuthenticationBackend,AuthenticationError,SimpleUser)fromstarlette.middlewareimportMiddlewarefromstarlette.middleware.authenticationimportAuthenticationMiddlewarefromstarlette.responsesimportPlainTextResponsefromstarlette.routingimportRouteimportbase64importbinasciiclassBasicAuthBackend(AuthenticationBackend):asyncdefauthenticate(self,conn):if"Authorization"notinconn.headers:returnauth=conn.headers["Authorization"]try:scheme,credentials=auth.split()ifscheme.lower()!='basic':returndecoded=base64.b64decode(credentials).decode("ascii")except(ValueError,UnicodeDecodeError,binascii.Error)asexc:raiseAuthenticationError('Invalid basic auth credentials')username,_,password=decoded.partition(":")# TODO: You'd want to verify the username and password here.returnAuthCredentials(["authenticated"]),SimpleUser(username)asyncdefhomepage(request):ifrequest.user.is_authenticated:returnPlainTextResponse('Hello, '+request.user.display_name)returnPlainTextResponse('Hello, you')routes=[Route("/",endpoint=homepage)]middleware=[Middleware(AuthenticationMiddleware,backend=BasicAuthBackend())]app=Starlette(routes=routes,middleware=middleware)
Users
OnceAuthenticationMiddleware is installed therequest.user interfacewill be available to endpoints or other middleware.
This interface should subclassBaseUser, which provides two properties,as well as whatever other information your user model includes.
.is_authenticated.display_name
Starlette provides two built-in user implementations:UnauthenticatedUser(),andSimpleUser(username).
AuthCredentials
It is important that authentication credentials are treated as separate conceptfrom users. An authentication scheme should be able to restrict or grantparticular privileges independently of the user identity.
TheAuthCredentials class provides the basic interface thatrequest.authexposes:
Permissions
Permissions are implemented as an endpoint decorator, that enforces that theincoming request includes the required authentication scopes.
fromstarlette.authenticationimportrequires@requires('authenticated')asyncdefdashboard(request):...
You can include either one or multiple required scopes:
fromstarlette.authenticationimportrequires@requires(['authenticated','admin'])asyncdefdashboard(request):...
By default 403 responses will be returned when permissions are not granted.In some cases you might want to customize this, for example to hide informationabout the URL layout from unauthenticated users.
fromstarlette.authenticationimportrequires@requires(['authenticated','admin'],status_code=404)asyncdefdashboard(request):...
Note
Thestatus_code parameter is not supported with WebSockets. The 403 (Forbidden)status code will always be used for those.
Alternatively you might want to redirect unauthenticated users to a differentpage.
fromstarlette.authenticationimportrequiresasyncdefhomepage(request):...@requires('authenticated',redirect='homepage')asyncdefdashboard(request):...
When redirecting users, the page you redirect them to will include URL they originally requested at thenext query param:
fromstarlette.authenticationimportrequiresfromstarlette.responsesimportRedirectResponse@requires('authenticated',redirect='login')asyncdefadmin(request):...asyncdeflogin(request):ifrequest.method=="POST":# Now that the user is authenticated,# we can send them to their original request destinationifrequest.user.is_authenticated:next_url=request.query_params.get("next")ifnext_url:returnRedirectResponse(next_url)returnRedirectResponse("/")
For class-based endpoints, you should wrap the decoratoraround a method on the class.
fromstarlette.authenticationimportrequiresfromstarlette.endpointsimportHTTPEndpointclassDashboard(HTTPEndpoint):@requires("authenticated")asyncdefget(self,request):...
Custom authentication error responses
You can customise the error response sent when aAuthenticationError israised by an auth backend:
fromstarlette.applicationsimportStarlettefromstarlette.middlewareimportMiddlewarefromstarlette.middleware.authenticationimportAuthenticationMiddlewarefromstarlette.requestsimportRequestfromstarlette.responsesimportJSONResponsedefon_auth_error(request:Request,exc:Exception):returnJSONResponse({"error":str(exc)},status_code=401)app=Starlette(middleware=[Middleware(AuthenticationMiddleware,backend=BasicAuthBackend(),on_error=on_auth_error),],)