Skip to content

Commit afe41f5

Browse files
committed
Update authentication to handle JWT token in backend
1 parent 2584e85 commit afe41f5

25 files changed

Lines changed: 94 additions & 279 deletions

File tree

airflow-core/docs/core-concepts/auth-manager/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ cookie named ``_token`` before redirecting to the Airflow UI. The Airflow UI wil
166166
response = RedirectResponse(url="/")
167167
168168
secure = request.base_url.scheme == "https" or bool(conf.get("api", "ssl_cert", fallback=""))
169-
response.set_cookie(COOKIE_NAME_JWT_TOKEN, token, secure=secure)
169+
response.set_cookie(COOKIE_NAME_JWT_TOKEN, token, secure=secure, httponly=True)
170170
return response
171171
172172
.. note::

airflow-core/src/airflow/api_fastapi/app.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
init_config,
3030
init_error_handlers,
3131
init_flask_plugins,
32-
init_middlewares,
3332
init_ui_plugins,
3433
init_views,
3534
)
@@ -100,7 +99,6 @@ def create_app(apps: str = "all") -> FastAPI:
10099
init_ui_plugins(app)
101100
init_views(app) # Core views need to be the last routes added - it has a catch all route
102101
init_error_handlers(app)
103-
init_middlewares(app)
104102

105103
init_config(app)
106104

airflow-core/src/airflow/api_fastapi/auth/managers/simple/routes/login.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def login_all_admins(request: Request) -> RedirectResponse:
9494
COOKIE_NAME_JWT_TOKEN,
9595
SimpleAuthManagerLogin.create_token_all_admins(),
9696
secure=secure,
97+
httponly=True,
9798
)
9899
return response
99100

airflow-core/src/airflow/api_fastapi/core_api/app.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -181,17 +181,6 @@ def init_error_handlers(app: FastAPI) -> None:
181181
app.add_exception_handler(handler.exception_cls, handler.exception_handler)
182182

183183

184-
def init_middlewares(app: FastAPI) -> None:
185-
from airflow.configuration import conf
186-
187-
if "SimpleAuthManager" in conf.get("core", "auth_manager") and conf.getboolean(
188-
"core", "simple_auth_manager_all_admins"
189-
):
190-
from airflow.api_fastapi.auth.managers.simple.middleware import SimpleAllAdminMiddleware
191-
192-
app.add_middleware(SimpleAllAdminMiddleware)
193-
194-
195184
def init_ui_plugins(app: FastAPI) -> None:
196185
"""Initialize UI plugins."""
197186
from airflow import plugins_manager

airflow-core/src/airflow/api_fastapi/core_api/security.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from pydantic import NonNegativeInt
2828

2929
from airflow.api_fastapi.app import get_auth_manager
30+
from airflow.api_fastapi.auth.managers.base_auth_manager import COOKIE_NAME_JWT_TOKEN
3031
from airflow.api_fastapi.auth.managers.models.base_user import BaseUser
3132
from airflow.api_fastapi.auth.managers.models.batch_apis import (
3233
IsAuthorizedConnectionRequest,
@@ -96,14 +97,22 @@ async def resolve_user_from_token(token_str: str | None) -> BaseUser:
9697

9798

9899
async def get_user(
100+
request: Request,
99101
oauth_token: str | None = Depends(oauth2_scheme),
100102
bearer_credentials: HTTPAuthorizationCredentials | None = Depends(bearer_scheme),
101103
) -> BaseUser:
102-
token_str = None
104+
# A user might have been already built by a middleware, if so, it is stored in `request.state.user`
105+
user: BaseUser | None = getattr(request.state, "user", None)
106+
if user:
107+
return user
108+
109+
token_str: str | None
103110
if bearer_credentials and bearer_credentials.scheme.lower() == "bearer":
104111
token_str = bearer_credentials.credentials
105112
elif oauth_token:
106113
token_str = oauth_token
114+
else:
115+
token_str = request.cookies.get(COOKIE_NAME_JWT_TOKEN)
107116

108117
return await resolve_user_from_token(token_str)
109118

airflow-core/src/airflow/ui/openapi-gen/queries/common.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -763,12 +763,6 @@ export const useLoginServiceLogoutKey = "LoginServiceLogout";
763763
export const UseLoginServiceLogoutKeyFn = ({ next }: {
764764
next?: string;
765765
} = {}, queryKey?: Array<unknown>) => [useLoginServiceLogoutKey, ...(queryKey ?? [{ next }])];
766-
export type LoginServiceRefreshDefaultResponse = Awaited<ReturnType<typeof LoginService.refresh>>;
767-
export type LoginServiceRefreshQueryResult<TData = LoginServiceRefreshDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
768-
export const useLoginServiceRefreshKey = "LoginServiceRefresh";
769-
export const UseLoginServiceRefreshKeyFn = ({ next }: {
770-
next?: string;
771-
} = {}, queryKey?: Array<unknown>) => [useLoginServiceRefreshKey, ...(queryKey ?? [{ next }])];
772766
export type AuthLinksServiceGetAuthMenusDefaultResponse = Awaited<ReturnType<typeof AuthLinksService.getAuthMenus>>;
773767
export type AuthLinksServiceGetAuthMenusQueryResult<TData = AuthLinksServiceGetAuthMenusDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
774768
export const useAuthLinksServiceGetAuthMenusKey = "AuthLinksServiceGetAuthMenus";

airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,17 +1451,6 @@ export const ensureUseLoginServiceLogoutData = (queryClient: QueryClient, { next
14511451
next?: string;
14521452
} = {}) => queryClient.ensureQueryData({ queryKey: Common.UseLoginServiceLogoutKeyFn({ next }), queryFn: () => LoginService.logout({ next }) });
14531453
/**
1454-
* Refresh
1455-
* Refresh the authentication token.
1456-
* @param data The data for the request.
1457-
* @param data.next
1458-
* @returns unknown Successful Response
1459-
* @throws ApiError
1460-
*/
1461-
export const ensureUseLoginServiceRefreshData = (queryClient: QueryClient, { next }: {
1462-
next?: string;
1463-
} = {}) => queryClient.ensureQueryData({ queryKey: Common.UseLoginServiceRefreshKeyFn({ next }), queryFn: () => LoginService.refresh({ next }) });
1464-
/**
14651454
* Get Auth Menus
14661455
* @returns MenuItemCollectionResponse Successful Response
14671456
* @throws ApiError

airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,17 +1451,6 @@ export const prefetchUseLoginServiceLogout = (queryClient: QueryClient, { next }
14511451
next?: string;
14521452
} = {}) => queryClient.prefetchQuery({ queryKey: Common.UseLoginServiceLogoutKeyFn({ next }), queryFn: () => LoginService.logout({ next }) });
14531453
/**
1454-
* Refresh
1455-
* Refresh the authentication token.
1456-
* @param data The data for the request.
1457-
* @param data.next
1458-
* @returns unknown Successful Response
1459-
* @throws ApiError
1460-
*/
1461-
export const prefetchUseLoginServiceRefresh = (queryClient: QueryClient, { next }: {
1462-
next?: string;
1463-
} = {}) => queryClient.prefetchQuery({ queryKey: Common.UseLoginServiceRefreshKeyFn({ next }), queryFn: () => LoginService.refresh({ next }) });
1464-
/**
14651454
* Get Auth Menus
14661455
* @returns MenuItemCollectionResponse Successful Response
14671456
* @throws ApiError

airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,17 +1451,6 @@ export const useLoginServiceLogout = <TData = Common.LoginServiceLogoutDefaultRe
14511451
next?: string;
14521452
} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey: Common.UseLoginServiceLogoutKeyFn({ next }, queryKey), queryFn: () => LoginService.logout({ next }) as TData, ...options });
14531453
/**
1454-
* Refresh
1455-
* Refresh the authentication token.
1456-
* @param data The data for the request.
1457-
* @param data.next
1458-
* @returns unknown Successful Response
1459-
* @throws ApiError
1460-
*/
1461-
export const useLoginServiceRefresh = <TData = Common.LoginServiceRefreshDefaultResponse, TError = unknown, TQueryKey extends Array<unknown> = unknown[]>({ next }: {
1462-
next?: string;
1463-
} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey: Common.UseLoginServiceRefreshKeyFn({ next }, queryKey), queryFn: () => LoginService.refresh({ next }) as TData, ...options });
1464-
/**
14651454
* Get Auth Menus
14661455
* @returns MenuItemCollectionResponse Successful Response
14671456
* @throws ApiError

airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,17 +1451,6 @@ export const useLoginServiceLogoutSuspense = <TData = Common.LoginServiceLogoutD
14511451
next?: string;
14521452
} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey: Common.UseLoginServiceLogoutKeyFn({ next }, queryKey), queryFn: () => LoginService.logout({ next }) as TData, ...options });
14531453
/**
1454-
* Refresh
1455-
* Refresh the authentication token.
1456-
* @param data The data for the request.
1457-
* @param data.next
1458-
* @returns unknown Successful Response
1459-
* @throws ApiError
1460-
*/
1461-
export const useLoginServiceRefreshSuspense = <TData = Common.LoginServiceRefreshDefaultResponse, TError = unknown, TQueryKey extends Array<unknown> = unknown[]>({ next }: {
1462-
next?: string;
1463-
} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey: Common.UseLoginServiceRefreshKeyFn({ next }, queryKey), queryFn: () => LoginService.refresh({ next }) as TData, ...options });
1464-
/**
14651454
* Get Auth Menus
14661455
* @returns MenuItemCollectionResponse Successful Response
14671456
* @throws ApiError

0 commit comments

Comments
 (0)