diff --git a/console2/src/components/pages/UnauthorizedPage/index.tsx b/console2/src/components/pages/UnauthorizedPage/index.tsx
index 6914918742..62f737b88b 100644
--- a/console2/src/components/pages/UnauthorizedPage/index.tsx
+++ b/console2/src/components/pages/UnauthorizedPage/index.tsx
@@ -23,17 +23,11 @@ import * as React from 'react';
 import { RedirectButton } from '../../organisms';
 
 import './styles.css';
-import { Card, CardContent, CardHeader, Divider, Image } from 'semantic-ui-react';
-import { useContext, useEffect } from 'react';
-import { UserSessionContext } from '../../../session';
-
-export default () => {
-    const session = useContext(UserSessionContext);
-
-    useEffect(() => {
-        session.setUserInfo(undefined);
-    }, [session]);
+import {Card, CardContent, CardDescription, CardHeader, Divider, Image} from 'semantic-ui-react';
+import {withRouter} from "react-router";
 
+export default withRouter((props) => {
+    const error = new URLSearchParams(props.location.search).get('error');
     return (
         
             
@@ -42,6 +36,8 @@ export default () => {
 
                     You are not authorized.
 
+                    {error && Error: {error}}
+
                     
 
                     
@@ -51,4 +47,4 @@ export default () => {
             
          
     );
-};
+});
diff --git a/server/dist/src/main/resources/concord-server.conf b/server/dist/src/main/resources/concord-server.conf
index 673920fac7..1473632e8f 100644
--- a/server/dist/src/main/resources/concord-server.conf
+++ b/server/dist/src/main/resources/concord-server.conf
@@ -589,6 +589,7 @@ concord-server {
         urlBase = "http://concord.example.com"
         afterLoginUrl = "http://concord.example.com"
         afterLogoutUrl = "http://concord.example.com/#/logout/done"
+        onErrorUrl = "http://concord.example.com/#/unauthorized"
 
         scopes = [ "openid", "profile", "email", "groups"]
 
diff --git a/server/plugins/oidc/README.md b/server/plugins/oidc/README.md
index 8480bd5954..fb027f3b4c 100644
--- a/server/plugins/oidc/README.md
+++ b/server/plugins/oidc/README.md
@@ -23,6 +23,23 @@ concord-server {
 }
 ```
 
+For running in development mode (i.e. on `localhost`), callback URLs must be
+in the form of
+
+```
+http://localhost:8001/api/service/oidc/callback?client_name=oidc
+```
+
+Note the `client_name=oidc` query parameter, it is required by the plugin and
+must be present in the provider's configuration.
+
+The plugin uses the following scopes: `openid`, `profile`, `email`, `groups`.
+Which may or may not be enabled by default in the provider's configuration.
+
+Okta, for example, does not provide the `groups` scope by default. You can
+add it in the "Security" -> "API" -> "Authorization Servers" -> your_server ->
+"Scope" section.
+
 ### Interactive Login
 
 Configure the Concord Console to use custom logout/login URLs:
diff --git a/server/plugins/oidc/src/main/java/com/walmartlabs/concord/server/plugins/oidc/OidcAuthFilter.java b/server/plugins/oidc/src/main/java/com/walmartlabs/concord/server/plugins/oidc/OidcAuthFilter.java
index fcdff9df34..fe84070e8b 100644
--- a/server/plugins/oidc/src/main/java/com/walmartlabs/concord/server/plugins/oidc/OidcAuthFilter.java
+++ b/server/plugins/oidc/src/main/java/com/walmartlabs/concord/server/plugins/oidc/OidcAuthFilter.java
@@ -37,30 +37,42 @@ public class OidcAuthFilter implements Filter {
 
     public static final String URL = "/api/service/oidc/auth";
 
-    private final Config config;
+    private final PluginConfiguration pluginConfig;
+    private final Config oidcConfig;
     private final OidcClient> client;
 
     @Inject
-    public OidcAuthFilter(@Named("oidc") Config config, OidcClient> client) {
-        this.config = config;
+    public OidcAuthFilter(PluginConfiguration pluginConfig, @Named("oidc") Config oidcConfig, OidcClient> client) {
+        this.pluginConfig = pluginConfig;
+        this.oidcConfig = oidcConfig;
         this.client = client;
+
+        if (pluginConfig.isEnabled() && !client.isInitialized()) {
+            client.init();
+        }
     }
 
     @Override
     @SuppressWarnings("unchecked")
-    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException {
         HttpServletRequest req = (HttpServletRequest) request;
         HttpServletResponse resp = (HttpServletResponse) response;
 
+        if (!pluginConfig.isEnabled()) {
+            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "OIDC disabled");
+            return;
+        }
+
         JEEContext context = new JEEContext(req, resp);
 
         String redirectUrl = req.getParameter("from");
         context.getSessionStore().set(context, Pac4jConstants.REQUESTED_URL, redirectUrl);
 
-        RedirectionAction action = client.getRedirectionAction(context)
+        RedirectionAction action = client.getRedirectionActionBuilder()
+                .getRedirectionAction(context)
                 .orElseThrow(() -> new IllegalStateException("Can't get a redirection action for the request"));
 
-        config.getHttpActionAdapter().adapt(action, context);
+        oidcConfig.getHttpActionAdapter().adapt(action, context);
     }
 
     @Override
diff --git a/server/plugins/oidc/src/main/java/com/walmartlabs/concord/server/plugins/oidc/OidcCallbackFilter.java b/server/plugins/oidc/src/main/java/com/walmartlabs/concord/server/plugins/oidc/OidcCallbackFilter.java
index 9313d6da46..b72f273ff3 100644
--- a/server/plugins/oidc/src/main/java/com/walmartlabs/concord/server/plugins/oidc/OidcCallbackFilter.java
+++ b/server/plugins/oidc/src/main/java/com/walmartlabs/concord/server/plugins/oidc/OidcCallbackFilter.java
@@ -72,6 +72,16 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
             postLoginUrl = cfg.getAfterLoginUrl();
         }
 
+        String error = req.getParameter("error");
+        if (error != null) {
+            String derivedError = "unknown";
+            if ("access_denied".equals(error)) {
+                derivedError = "oidc_access_denied";
+            }
+            resp.sendRedirect(resp.encodeRedirectURL(cfg.getOnErrorUrl() + "?from=" + postLoginUrl + "&error=" + derivedError));
+            return;
+        }
+
         try {
             CallbackLogic, JEEContext> callback = pac4jConfig.getCallbackLogic();
             callback.perform(context, pac4jConfig, pac4jConfig.getHttpActionAdapter(), postLoginUrl, true, false, true, OidcPluginModule.CLIENT_NAME);
diff --git a/server/plugins/oidc/src/main/java/com/walmartlabs/concord/server/plugins/oidc/PluginConfiguration.java b/server/plugins/oidc/src/main/java/com/walmartlabs/concord/server/plugins/oidc/PluginConfiguration.java
index 811e09d7d4..46ff96b772 100644
--- a/server/plugins/oidc/src/main/java/com/walmartlabs/concord/server/plugins/oidc/PluginConfiguration.java
+++ b/server/plugins/oidc/src/main/java/com/walmartlabs/concord/server/plugins/oidc/PluginConfiguration.java
@@ -58,6 +58,10 @@ public class PluginConfiguration {
     @Config("oidc.afterLogoutUrl")
     private String afterLogoutUrl;
 
+    @Inject
+    @Config("oidc.onErrorUrl")
+    private String onErrorUrl;
+
     @Inject
     @Nullable
     @Config("oidc.scopes")
@@ -102,6 +106,10 @@ public String getAfterLogoutUrl() {
         return afterLogoutUrl;
     }
 
+    public String getOnErrorUrl() {
+        return onErrorUrl;
+    }
+
     public List getScopes() {
         return scopes;
     }