diff --git a/client/src/api/schema/schema.ts b/client/src/api/schema/schema.ts
index 1f94efde46d7..0669b9c6b79f 100644
--- a/client/src/api/schema/schema.ts
+++ b/client/src/api/schema/schema.ts
@@ -36796,7 +36796,8 @@ export interface operations {
query: {
/** @description Base-64 encoded JSON used to route request within Galaxy. */
state: string;
- code: string;
+ code?: string | null;
+ error?: string | null;
};
header?: {
/** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */
diff --git a/client/src/components/FileSources/Templates/CreateUserFileSource.vue b/client/src/components/FileSources/Templates/CreateUserFileSource.vue
index 5cc4a9f8e3aa..af85f683434e 100644
--- a/client/src/components/FileSources/Templates/CreateUserFileSource.vue
+++ b/client/src/components/FileSources/Templates/CreateUserFileSource.vue
@@ -1,5 +1,6 @@
+
+
+ {{ errorMessage }}
+
+
diff --git a/client/src/entry/analysis/router.js b/client/src/entry/analysis/router.js
index cfd6a815b73e..837e70a574bc 100644
--- a/client/src/entry/analysis/router.js
+++ b/client/src/entry/analysis/router.js
@@ -395,6 +395,11 @@ export function getRouter(Galaxy) {
{
path: "file_source_instances/create",
component: CreateUserFileSource,
+ props: (route) => {
+ return {
+ error: route.params.error,
+ };
+ },
},
{
path: "file_source_instances/index",
diff --git a/lib/galaxy/webapps/galaxy/api/oauth2_callback.py b/lib/galaxy/webapps/galaxy/api/oauth2_callback.py
index bb7968d89c58..a24f6b127df6 100644
--- a/lib/galaxy/webapps/galaxy/api/oauth2_callback.py
+++ b/lib/galaxy/webapps/galaxy/api/oauth2_callback.py
@@ -1,3 +1,5 @@
+from typing import Optional
+
from fastapi import Query
from fastapi.responses import RedirectResponse
@@ -16,13 +18,19 @@
title="State information sent with auth request",
description="Base-64 encoded JSON used to route request within Galaxy.",
)
-CodeQueryParam: str = Query(
- ...,
+CodeQueryParam: Optional[str] = Query(
+ None,
title="OAuth2 Authorization Code from remote resource",
)
+ErrorQueryParam: Optional[str] = Query(
+ None,
+ title="OAuth2 Error from remote resource",
+)
router = Router(tags=["oauth2"])
+ERROR_REDIRECT_PATH = "file_source_instances/create"
+
@router.cbv
class OAuth2Callback:
@@ -36,8 +44,16 @@ def oauth2_callback(
self,
trans: SessionRequestContext = DependsOnTrans,
state: str = StateQueryParam,
- code: str = CodeQueryParam,
+ code: Optional[str] = CodeQueryParam,
+ error: Optional[str] = ErrorQueryParam,
):
+ if error:
+ return RedirectResponse(f"{trans.request.url_path}{ERROR_REDIRECT_PATH}?error={error}")
+ elif not code:
+ return RedirectResponse(
+ f"{trans.request.url_path}{ERROR_REDIRECT_PATH}?error=No credentials provided, please try again."
+ )
+
oauth2_state = OAuth2State.decode(state)
# TODO: save session information in cookie to verify not CSRF with oauth2_state.nonce
route = oauth2_state.route