AuthorizationException Getting lost in Shiro

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

AuthorizationException Getting lost in Shiro

jeff saremi
The code I am looking at is a part of knox 1.1 which uses Shiro for authentication

Might have been solved in later versions

I am investigating this stack trace:

Caused by: org.apache.shiro.authz.AuthorizationException: There was a SQL error while authorizing user [admin]
         at org.apache.shiro.realm.jdbc.JdbcRealm.doGetAuthorizationInfo(JdbcRealm.java:345)
         at org.apache.shiro.realm.AuthorizingRealm.getAuthorizationInfo(AuthorizingRealm.java:341)
         at org.apache.shiro.realm.AuthorizingRealm.hasRole(AuthorizingRealm.java:573)
         at org.apache.shiro.authz.ModularRealmAuthorizer.hasRole(ModularRealmAuthorizer.java:374)
         at org.apache.shiro.mgt.AuthorizingSecurityManager.hasRole(AuthorizingSecurityManager.java:153)
         at org.apache.shiro.subject.support.DelegatingSubject.hasRole(DelegatingSubject.java:224)
         at org.apache.knox.gateway.filter.ShiroSubjectIdentityAdapter.doFilter(ShiroSubjectIdentityAdapter.java:69)
         at org.apache.knox.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:372)
         at org.apache.knox.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:272)
         at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
         at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
         at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
         ... 52 more
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'roles_permissions'.
         at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:254)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1608)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:578)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:508)
         at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7240)
         at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2869)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:243)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:218)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:434)
         at org.apache.shiro.realm.jdbc.JdbcRealm.getPermissions(JdbcRealm.java:401)
         at org.apache.shiro.realm.jdbc.JdbcRealm.doGetAuthorizationInfo(JdbcRealm.java:335)


This is logged in knox and an http 500 is returned to the caller, instead of a 401

I have checked the following:
  • SQLServerException is a valid subclass of SqlException
  • doGetAuthorizationInfo catches this error and throws an AuthorizationException
            roleNames = getRoleNamesForUser(conn, username);
            if (permissionsLookupEnabled) {
                permissions = getPermissions(conn, username, roleNames);
            }

        } catch (SQLException e) {
            final String message = "There was a SQL error while authorizing user [" + username + "]";
            if (log.isErrorEnabled()) {
                log.error(message, e);
            }

            // Rethrow any SQL errors as an authorization exception
            throw new AuthorizationException(message, e);

  • doFilter() of ShiroSubjectIdentityAdapter has no catches around the hasRole() call:
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
   
    Subject subject = SecurityUtils.getSubject();
   
    // trigger call to shiro authorization realm
    // we use shiro authorization realm to look up groups
    subject.hasRole("authenticatedUser");

    CallableChain callableChain = new CallableChain(request, response, chain);
    SecurityUtils.getSubject().execute(callableChain);
  }
  • hasRole() does not declare an exception and AuthorizationException is ultimately a subclass of RuntimeException
  • AdviceFilter.cleanup() called from doFilter() seems to be wrapping this exception as a ServletException which might have caused this to be caught like a generic exception and a 500 returned instead:
        if (exception != null) {
            if (exception instanceof ServletException) {
                throw (ServletException) exception;
            } else if (exception instanceof IOException) {
                throw (IOException) exception;
            } else {
                if (log.isDebugEnabled()) {
                    String msg = "Filter execution resulted in an unexpected Exception " +
                            "(not IOException or ServletException as the Filter API recommends).  " +
                            "Wrapping in ServletException and propagating.";
                    log.debug(msg);
                }
                throw new ServletException(exception);
            }
        }

Did we lose a good, useful AuthorizationException? or is there more to this that I'm no reading properly?

Reply | Threaded
Open this post in threaded view
|

Re: AuthorizationException Getting lost in Shiro

fpapon

Hi,


I checked the Apache Knox project and the 1.1 version use the 1.2.6 version of Apache Shiro.


The latest 1.3.0 of Knox use the latest 1.4.1 of Shiro.


Can you make a test with the 1.3.0 of Knox?


regards,

François
[hidden email]
Le 11/09/2019 à 01:54, jeff saremi a écrit :
The code I am looking at is a part of knox 1.1 which uses Shiro for authentication

Might have been solved in later versions

I am investigating this stack trace:

Caused by: org.apache.shiro.authz.AuthorizationException: There was a SQL error while authorizing user [admin]
         at org.apache.shiro.realm.jdbc.JdbcRealm.doGetAuthorizationInfo(JdbcRealm.java:345)
         at org.apache.shiro.realm.AuthorizingRealm.getAuthorizationInfo(AuthorizingRealm.java:341)
         at org.apache.shiro.realm.AuthorizingRealm.hasRole(AuthorizingRealm.java:573)
         at org.apache.shiro.authz.ModularRealmAuthorizer.hasRole(ModularRealmAuthorizer.java:374)
         at org.apache.shiro.mgt.AuthorizingSecurityManager.hasRole(AuthorizingSecurityManager.java:153)
         at org.apache.shiro.subject.support.DelegatingSubject.hasRole(DelegatingSubject.java:224)
         at org.apache.knox.gateway.filter.ShiroSubjectIdentityAdapter.doFilter(ShiroSubjectIdentityAdapter.java:69)
         at org.apache.knox.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:372)
         at org.apache.knox.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:272)
         at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
         at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
         at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
         ... 52 more
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'roles_permissions'.
         at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:254)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1608)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:578)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:508)
         at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7240)
         at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2869)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:243)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:218)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:434)
         at org.apache.shiro.realm.jdbc.JdbcRealm.getPermissions(JdbcRealm.java:401)
         at org.apache.shiro.realm.jdbc.JdbcRealm.doGetAuthorizationInfo(JdbcRealm.java:335)


This is logged in knox and an http 500 is returned to the caller, instead of a 401

I have checked the following:
  • SQLServerException is a valid subclass of SqlException
  • doGetAuthorizationInfo catches this error and throws an AuthorizationException
            roleNames = getRoleNamesForUser(conn, username);
            if (permissionsLookupEnabled) {
                permissions = getPermissions(conn, username, roleNames);
            }

        } catch (SQLException e) {
            final String message = "There was a SQL error while authorizing user [" + username + "]";
            if (log.isErrorEnabled()) {
                log.error(message, e);
            }

            // Rethrow any SQL errors as an authorization exception
            throw new AuthorizationException(message, e);

  • doFilter() of ShiroSubjectIdentityAdapter has no catches around the hasRole() call:
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
   
    Subject subject = SecurityUtils.getSubject();
   
    // trigger call to shiro authorization realm
    // we use shiro authorization realm to look up groups
    subject.hasRole("authenticatedUser");

    CallableChain callableChain = new CallableChain(request, response, chain);
    SecurityUtils.getSubject().execute(callableChain);
  }
  • hasRole() does not declare an exception and AuthorizationException is ultimately a subclass of RuntimeException
  • AdviceFilter.cleanup() called from doFilter() seems to be wrapping this exception as a ServletException which might have caused this to be caught like a generic exception and a 500 returned instead:
        if (exception != null) {
            if (exception instanceof ServletException) {
                throw (ServletException) exception;
            } else if (exception instanceof IOException) {
                throw (IOException) exception;
            } else {
                if (log.isDebugEnabled()) {
                    String msg = "Filter execution resulted in an unexpected Exception " +
                            "(not IOException or ServletException as the Filter API recommends).  " +
                            "Wrapping in ServletException and propagating.";
                    log.debug(msg);
                }
                throw new ServletException(exception);
            }
        }

Did we lose a good, useful AuthorizationException? or is there more to this that I'm no reading properly?

Reply | Threaded
Open this post in threaded view
|

Re: AuthorizationException Getting lost in Shiro

jeff saremi
Unfortunately this is very hard for us to reproduce and even harder to upgrade and ask someone to try
This is a part of a more complex product and the problem was reported by some of our customers.
I am at this stage not too concerned with a fix. But rather the analysis of where the problem is.
Was my logic sound? Did I track it to the right spot? Where could Shiro be messing up a valid exception and re-throw it as a generic exception?


From: Francois Papon <[hidden email]>
Sent: Wednesday, September 11, 2019 5:24 AM
To: [hidden email] <[hidden email]>
Subject: Re: AuthorizationException Getting lost in Shiro
 

Hi,


I checked the Apache Knox project and the 1.1 version use the 1.2.6 version of Apache Shiro.


The latest 1.3.0 of Knox use the latest 1.4.1 of Shiro.


Can you make a test with the 1.3.0 of Knox?


regards,

François
[hidden email]
Le 11/09/2019 à 01:54, jeff saremi a écrit :
The code I am looking at is a part of knox 1.1 which uses Shiro for authentication

Might have been solved in later versions

I am investigating this stack trace:

Caused by: org.apache.shiro.authz.AuthorizationException: There was a SQL error while authorizing user [admin]
         at org.apache.shiro.realm.jdbc.JdbcRealm.doGetAuthorizationInfo(JdbcRealm.java:345)
         at org.apache.shiro.realm.AuthorizingRealm.getAuthorizationInfo(AuthorizingRealm.java:341)
         at org.apache.shiro.realm.AuthorizingRealm.hasRole(AuthorizingRealm.java:573)
         at org.apache.shiro.authz.ModularRealmAuthorizer.hasRole(ModularRealmAuthorizer.java:374)
         at org.apache.shiro.mgt.AuthorizingSecurityManager.hasRole(AuthorizingSecurityManager.java:153)
         at org.apache.shiro.subject.support.DelegatingSubject.hasRole(DelegatingSubject.java:224)
         at org.apache.knox.gateway.filter.ShiroSubjectIdentityAdapter.doFilter(ShiroSubjectIdentityAdapter.java:69)
         at org.apache.knox.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:372)
         at org.apache.knox.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:272)
         at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
         at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
         at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
         ... 52 more
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'roles_permissions'.
         at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:254)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1608)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:578)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:508)
         at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7240)
         at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2869)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:243)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:218)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:434)
         at org.apache.shiro.realm.jdbc.JdbcRealm.getPermissions(JdbcRealm.java:401)
         at org.apache.shiro.realm.jdbc.JdbcRealm.doGetAuthorizationInfo(JdbcRealm.java:335)


This is logged in knox and an http 500 is returned to the caller, instead of a 401

I have checked the following:
  • SQLServerException is a valid subclass of SqlException
  • doGetAuthorizationInfo catches this error and throws an AuthorizationException
            roleNames = getRoleNamesForUser(conn, username);
            if (permissionsLookupEnabled) {
                permissions = getPermissions(conn, username, roleNames);
            }

        } catch (SQLException e) {
            final String message = "There was a SQL error while authorizing user [" + username + "]";
            if (log.isErrorEnabled()) {
                log.error(message, e);
            }

            // Rethrow any SQL errors as an authorization exception
            throw new AuthorizationException(message, e);

  • doFilter() of ShiroSubjectIdentityAdapter has no catches around the hasRole() call:
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
   
    Subject subject = SecurityUtils.getSubject();
   
    // trigger call to shiro authorization realm
    // we use shiro authorization realm to look up groups
    subject.hasRole("authenticatedUser");

    CallableChain callableChain = new CallableChain(request, response, chain);
    SecurityUtils.getSubject().execute(callableChain);
  }
  • hasRole() does not declare an exception and AuthorizationException is ultimately a subclass of RuntimeException
  • AdviceFilter.cleanup() called from doFilter() seems to be wrapping this exception as a ServletException which might have caused this to be caught like a generic exception and a 500 returned instead:
        if (exception != null) {
            if (exception instanceof ServletException) {
                throw (ServletException) exception;
            } else if (exception instanceof IOException) {
                throw (IOException) exception;
            } else {
                if (log.isDebugEnabled()) {
                    String msg = "Filter execution resulted in an unexpected Exception " +
                            "(not IOException or ServletException as the Filter API recommends).  " +
                            "Wrapping in ServletException and propagating.";
                    log.debug(msg);
                }
                throw new ServletException(exception);
            }
        }

Did we lose a good, useful AuthorizationException? or is there more to this that I'm no reading properly?

Reply | Threaded
Open this post in threaded view
|

Re: AuthorizationException Getting lost in Shiro

Brian Demers
This likely depends how Shiro and the AdviceFitler was added into the project, we would need a way to reproduce the problem.

I would also strongly suggest updating as well.

Either way, the easiest way to reproduce this might be to create a realm that throws an AuthorizationException (you could extend one of the text-based realms), this would take your DB out of the equation.

Keep us posted!


On Wed, Sep 11, 2019 at 12:26 PM jeff saremi <[hidden email]> wrote:
Unfortunately this is very hard for us to reproduce and even harder to upgrade and ask someone to try
This is a part of a more complex product and the problem was reported by some of our customers.
I am at this stage not too concerned with a fix. But rather the analysis of where the problem is.
Was my logic sound? Did I track it to the right spot? Where could Shiro be messing up a valid exception and re-throw it as a generic exception?


From: Francois Papon <[hidden email]>
Sent: Wednesday, September 11, 2019 5:24 AM
To: [hidden email] <[hidden email]>
Subject: Re: AuthorizationException Getting lost in Shiro
 

Hi,


I checked the Apache Knox project and the 1.1 version use the 1.2.6 version of Apache Shiro.


The latest 1.3.0 of Knox use the latest 1.4.1 of Shiro.


Can you make a test with the 1.3.0 of Knox?


regards,

François
[hidden email]
Le 11/09/2019 à 01:54, jeff saremi a écrit :
The code I am looking at is a part of knox 1.1 which uses Shiro for authentication

Might have been solved in later versions

I am investigating this stack trace:

Caused by: org.apache.shiro.authz.AuthorizationException: There was a SQL error while authorizing user [admin]
         at org.apache.shiro.realm.jdbc.JdbcRealm.doGetAuthorizationInfo(JdbcRealm.java:345)
         at org.apache.shiro.realm.AuthorizingRealm.getAuthorizationInfo(AuthorizingRealm.java:341)
         at org.apache.shiro.realm.AuthorizingRealm.hasRole(AuthorizingRealm.java:573)
         at org.apache.shiro.authz.ModularRealmAuthorizer.hasRole(ModularRealmAuthorizer.java:374)
         at org.apache.shiro.mgt.AuthorizingSecurityManager.hasRole(AuthorizingSecurityManager.java:153)
         at org.apache.shiro.subject.support.DelegatingSubject.hasRole(DelegatingSubject.java:224)
         at org.apache.knox.gateway.filter.ShiroSubjectIdentityAdapter.doFilter(ShiroSubjectIdentityAdapter.java:69)
         at org.apache.knox.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:372)
         at org.apache.knox.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:272)
         at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
         at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
         at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
         ... 52 more
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'roles_permissions'.
         at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:254)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1608)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:578)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:508)
         at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7240)
         at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2869)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:243)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:218)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:434)
         at org.apache.shiro.realm.jdbc.JdbcRealm.getPermissions(JdbcRealm.java:401)
         at org.apache.shiro.realm.jdbc.JdbcRealm.doGetAuthorizationInfo(JdbcRealm.java:335)


This is logged in knox and an http 500 is returned to the caller, instead of a 401

I have checked the following:
  • SQLServerException is a valid subclass of SqlException
  • doGetAuthorizationInfo catches this error and throws an AuthorizationException
            roleNames = getRoleNamesForUser(conn, username);
            if (permissionsLookupEnabled) {
                permissions = getPermissions(conn, username, roleNames);
            }

        } catch (SQLException e) {
            final String message = "There was a SQL error while authorizing user [" + username + "]";
            if (log.isErrorEnabled()) {
                log.error(message, e);
            }

            // Rethrow any SQL errors as an authorization exception
            throw new AuthorizationException(message, e);

  • doFilter() of ShiroSubjectIdentityAdapter has no catches around the hasRole() call:
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
   
    Subject subject = SecurityUtils.getSubject();
   
    // trigger call to shiro authorization realm
    // we use shiro authorization realm to look up groups
    subject.hasRole("authenticatedUser");

    CallableChain callableChain = new CallableChain(request, response, chain);
    SecurityUtils.getSubject().execute(callableChain);
  }
  • hasRole() does not declare an exception and AuthorizationException is ultimately a subclass of RuntimeException
  • AdviceFilter.cleanup() called from doFilter() seems to be wrapping this exception as a ServletException which might have caused this to be caught like a generic exception and a 500 returned instead:
        if (exception != null) {
            if (exception instanceof ServletException) {
                throw (ServletException) exception;
            } else if (exception instanceof IOException) {
                throw (IOException) exception;
            } else {
                if (log.isDebugEnabled()) {
                    String msg = "Filter execution resulted in an unexpected Exception " +
                            "(not IOException or ServletException as the Filter API recommends).  " +
                            "Wrapping in ServletException and propagating.";
                    log.debug(msg);
                }
                throw new ServletException(exception);
            }
        }

Did we lose a good, useful AuthorizationException? or is there more to this that I'm no reading properly?

Reply | Threaded
Open this post in threaded view
|

Re: AuthorizationException Getting lost in Shiro

jeff saremi
great suggestions Brian. I'll work on doing a repro in an isolated environment

From: Brian Demers <[hidden email]>
Sent: Thursday, September 12, 2019 7:59 AM
To: [hidden email] <[hidden email]>
Subject: Re: AuthorizationException Getting lost in Shiro
 
This likely depends how Shiro and the AdviceFitler was added into the project, we would need a way to reproduce the problem.

I would also strongly suggest updating as well.

Either way, the easiest way to reproduce this might be to create a realm that throws an AuthorizationException (you could extend one of the text-based realms), this would take your DB out of the equation.

Keep us posted!


On Wed, Sep 11, 2019 at 12:26 PM jeff saremi <[hidden email]> wrote:
Unfortunately this is very hard for us to reproduce and even harder to upgrade and ask someone to try
This is a part of a more complex product and the problem was reported by some of our customers.
I am at this stage not too concerned with a fix. But rather the analysis of where the problem is.
Was my logic sound? Did I track it to the right spot? Where could Shiro be messing up a valid exception and re-throw it as a generic exception?


From: Francois Papon <[hidden email]>
Sent: Wednesday, September 11, 2019 5:24 AM
To: [hidden email] <[hidden email]>
Subject: Re: AuthorizationException Getting lost in Shiro
 

Hi,


I checked the Apache Knox project and the 1.1 version use the 1.2.6 version of Apache Shiro.


The latest 1.3.0 of Knox use the latest 1.4.1 of Shiro.


Can you make a test with the 1.3.0 of Knox?


regards,

François
[hidden email]
Le 11/09/2019 à 01:54, jeff saremi a écrit :
The code I am looking at is a part of knox 1.1 which uses Shiro for authentication

Might have been solved in later versions

I am investigating this stack trace:

Caused by: org.apache.shiro.authz.AuthorizationException: There was a SQL error while authorizing user [admin]
         at org.apache.shiro.realm.jdbc.JdbcRealm.doGetAuthorizationInfo(JdbcRealm.java:345)
         at org.apache.shiro.realm.AuthorizingRealm.getAuthorizationInfo(AuthorizingRealm.java:341)
         at org.apache.shiro.realm.AuthorizingRealm.hasRole(AuthorizingRealm.java:573)
         at org.apache.shiro.authz.ModularRealmAuthorizer.hasRole(ModularRealmAuthorizer.java:374)
         at org.apache.shiro.mgt.AuthorizingSecurityManager.hasRole(AuthorizingSecurityManager.java:153)
         at org.apache.shiro.subject.support.DelegatingSubject.hasRole(DelegatingSubject.java:224)
         at org.apache.knox.gateway.filter.ShiroSubjectIdentityAdapter.doFilter(ShiroSubjectIdentityAdapter.java:69)
         at org.apache.knox.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:372)
         at org.apache.knox.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:272)
         at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
         at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
         at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
         ... 52 more
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'roles_permissions'.
         at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:254)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1608)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:578)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:508)
         at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7240)
         at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2869)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:243)
         at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:218)
         at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:434)
         at org.apache.shiro.realm.jdbc.JdbcRealm.getPermissions(JdbcRealm.java:401)
         at org.apache.shiro.realm.jdbc.JdbcRealm.doGetAuthorizationInfo(JdbcRealm.java:335)


This is logged in knox and an http 500 is returned to the caller, instead of a 401

I have checked the following:
  • SQLServerException is a valid subclass of SqlException
  • doGetAuthorizationInfo catches this error and throws an AuthorizationException
            roleNames = getRoleNamesForUser(conn, username);
            if (permissionsLookupEnabled) {
                permissions = getPermissions(conn, username, roleNames);
            }

        } catch (SQLException e) {
            final String message = "There was a SQL error while authorizing user [" + username + "]";
            if (log.isErrorEnabled()) {
                log.error(message, e);
            }

            // Rethrow any SQL errors as an authorization exception
            throw new AuthorizationException(message, e);

  • doFilter() of ShiroSubjectIdentityAdapter has no catches around the hasRole() call:
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
   
    Subject subject = SecurityUtils.getSubject();
   
    // trigger call to shiro authorization realm
    // we use shiro authorization realm to look up groups
    subject.hasRole("authenticatedUser");

    CallableChain callableChain = new CallableChain(request, response, chain);
    SecurityUtils.getSubject().execute(callableChain);
  }
  • hasRole() does not declare an exception and AuthorizationException is ultimately a subclass of RuntimeException
  • AdviceFilter.cleanup() called from doFilter() seems to be wrapping this exception as a ServletException which might have caused this to be caught like a generic exception and a 500 returned instead:
        if (exception != null) {
            if (exception instanceof ServletException) {
                throw (ServletException) exception;
            } else if (exception instanceof IOException) {
                throw (IOException) exception;
            } else {
                if (log.isDebugEnabled()) {
                    String msg = "Filter execution resulted in an unexpected Exception " +
                            "(not IOException or ServletException as the Filter API recommends).  " +
                            "Wrapping in ServletException and propagating.";
                    log.debug(msg);
                }
                throw new ServletException(exception);
            }
        }

Did we lose a good, useful AuthorizationException? or is there more to this that I'm no reading properly?