diff --git a/pkg/webui/account/views/app/index.js b/pkg/webui/account/views/app/index.js
index c20d827f5be..8f4fd0adaae 100644
--- a/pkg/webui/account/views/app/index.js
+++ b/pkg/webui/account/views/app/index.js
@@ -82,7 +82,7 @@ const AccountApp = ({ history }) => {
defaultTitle={`${siteTitle ? `${siteTitle} - ` : ''}${siteName}`}
/>
-
+
diff --git a/pkg/webui/lib/components/full-view-error/error.js b/pkg/webui/lib/components/full-view-error/error.js
index f075746da2b..01e738a539c 100644
--- a/pkg/webui/lib/components/full-view-error/error.js
+++ b/pkg/webui/lib/components/full-view-error/error.js
@@ -100,7 +100,7 @@ const FullViewErrorInner = ({ error, safe }) => {
} else if (isOAuthCallback) {
errorTitle = errorMessages.loginFailed
errorMessage = errorMessages.loginFailedDescription
- if (isOAuthClientRefusedError(error)) {
+ if (isOAuthClientRefusedError(error) || error.error === 'access_denied') {
errorMessage = errorMessages.loginFailedAbortDescription
} else if (isOAuthInvalidStateError(error)) {
// Usually in case of state errors, the state has expired or otherwise
diff --git a/pkg/webui/lib/components/with-auth.js b/pkg/webui/lib/components/with-auth.js
index bcf8757fd01..56948d6e7de 100644
--- a/pkg/webui/lib/components/with-auth.js
+++ b/pkg/webui/lib/components/with-auth.js
@@ -13,7 +13,7 @@
// limitations under the License.
import React from 'react'
-import { useLocation, Navigate } from 'react-router-dom'
+import { useLocation, Navigate, useSearchParams } from 'react-router-dom'
import { defineMessages } from 'react-intl'
import Spinner from '@ttn-lw/components/spinner'
@@ -47,6 +47,7 @@ const m = defineMessages({
// `Auth` is a component that wraps a tree that requires the user to be authenticated.
const Auth = ({ user, fetching, userError, errorComponent, children, rights, isAdmin }) => {
const location = useLocation()
+ const [searchParams] = useSearchParams()
if (fetching) {
return (
@@ -56,8 +57,14 @@ const Auth = ({ user, fetching, userError, errorComponent, children, rights, isA
}
let error
+ const errorParam = searchParams.get('error')
+ const errorDesriptionParam = searchParams.get('error_description')
+ const isCallback = location.pathname.endsWith('/oauth/callback')
+ const hasCallbackError = isCallback && Boolean(errorParam)
- if (userError) {
+ if (hasCallbackError) {
+ error = { error: errorParam, error_description: errorDesriptionParam }
+ } else if (userError) {
error = userError
} else if (
// Check whether the user has at least basic rights, without which it
@@ -82,7 +89,7 @@ const Auth = ({ user, fetching, userError, errorComponent, children, rights, isA
if (error) {
// Redirect to root to prevent side effects.
- if (location.pathname !== '/') {
+ if (!hasCallbackError && location.pathname !== '/') {
return
}