Class OAuthAuthenticatingFilter

  • All Implemented Interfaces:
    javax.servlet.Filter, org.apache.shiro.util.Nameable, org.apache.shiro.web.filter.PathConfigProcessor

    public class OAuthAuthenticatingFilter
    extends org.apache.shiro.web.filter.authc.AuthenticatingFilter
    The flow here is (start = not authenticated request)

    1. shiro asks AuthenticatingFilter.isAccessAllowed(ServletRequest, ServletResponse, Object), which is false if subject is not authenticated
    2. onAccessDenied(ServletRequest, ServletResponse) is called, here we detect if this a pending login-attempt (roundtrip back from AD including auth-code token) or we save current request and initiate a redirect to oauth authorization server and set redirect_url to link back to us
    3. server responses with "code" http parameter, as so isLoginRequest(ServletRequest, ServletResponse) returns true here, as such onAccessDenied(ServletRequest, ServletResponse) triggers AuthenticatingFilter.executeLogin(ServletRequest, ServletResponse)
    4. AuthenticatingFilter.executeLogin(ServletRequest, ServletResponse) queries createToken(ServletRequest, ServletResponse) to create a token (which here is basically the auth-code we got from AD), this token is passed to Subject.login(AuthenticationToken)
    5. Shiro kicks in and asks each and every avaialable realm to process the authentication token delegated in previous step, our OAuthRealm connects to AD, queries for user-property we need internally (user-id) and returns as authenticated princial. No authorization is done on this level, just authentication, as such our oauth2 realm is authenticating only, and not authorizing
    6. whenever permission are checked, Shiro scans next realms to authorize, here our jdbcrealm loads properties from database according to prinpical (user-id)
    7. the onLoginSuccess(AuthenticationToken, Subject, ServletRequest, ServletResponse) is overriden as to delegate to AuthenticationFilter.issueSuccessRedirect(ServletRequest, ServletResponse) in order to redirect user to originally accessed url which was saved in step 2

        all final methods on these class define the flow and must not be changed.
    • Field Summary

      Fields 
      Modifier and Type Field Description
      protected java.lang.String authorizeEndpoint  
      protected java.lang.String authScope  
      protected java.lang.String clientId  
      protected java.lang.String optionalProviderId  
      protected java.lang.String redirectUrl  
      static java.lang.String SESSION_ATTR_KEY_AUTH_STATE  
      static java.lang.String SESSION_ATTR_KEY_ORIG_URL  
      static java.lang.String SESSION_ATTR_KEY_PROVIDER_INSTANCE_ID  
      protected java.lang.String successUrl  
      protected java.lang.String urlParameterName  
      • Fields inherited from class org.apache.shiro.web.filter.authc.AuthenticatingFilter

        PERMISSIVE
      • Fields inherited from class org.apache.shiro.web.filter.authc.AuthenticationFilter

        DEFAULT_SUCCESS_URL
      • Fields inherited from class org.apache.shiro.web.filter.AccessControlFilter

        DEFAULT_LOGIN_URL, GET_METHOD, POST_METHOD
      • Fields inherited from class org.apache.shiro.web.filter.PathMatchingFilter

        appliedPaths, pathMatcher
      • Fields inherited from class org.apache.shiro.web.servlet.OncePerRequestFilter

        ALREADY_FILTERED_SUFFIX
      • Fields inherited from class org.apache.shiro.web.servlet.AbstractFilter

        filterConfig
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      protected java.lang.String constructLoginUrl​(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)
      This method basically knows how to construct a login url to authority and delegate creation of redirect_uri to constructRedirectUrl(ServletRequest, ServletResponse).
      protected java.lang.String constructRedirectUrl​(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)  
      protected java.lang.String createStateValue()
      creates a state value used to prevent CRSF. this implementation creates UUID
      protected org.apache.shiro.authc.AuthenticationToken createToken​(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)  
      java.lang.String getAuthorizeEndpoint()  
      java.lang.String getAuthScope()  
      java.lang.String getClientId()  
      java.lang.String getOptionalProviderId()  
      java.lang.String getRedirectUrl()  
      java.lang.String getSuccessUrl()  
      java.lang.String getUrlParameterName()  
      protected boolean isEnabled​(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)
      supports .enable flag and also handles a round-trip from authorization server; in order to provide extend with your logic please override isEnabledByProvider(ServletRequest, ServletResponse)
      protected java.lang.Boolean isEnabledByProvider​(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)
      current implementation checks if parameter getUrlParameterName() equals to getOptionalProviderId().
      protected boolean isLoginRequest​(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)
      according to redirect_url set previously in redirectToLogin(ServletRequest, ServletResponse)
      protected boolean onAccessDenied​(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)
      handle AccessControlFilter.saveRequestAndRedirectToLogin(ServletRequest, ServletResponse) and redirection to authorization server, in addition creates a state, which is checked in isLoginRequest(ServletRequest, ServletResponse) to prevent CSRF and used in constructLoginUrl(ServletRequest, ServletResponse) to serialize a state to URL
      protected boolean onLoginSuccess​(org.apache.shiro.authc.AuthenticationToken token, org.apache.shiro.subject.Subject subject, javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)
      delegate here to AuthenticationFilter.issueSuccessRedirect(ServletRequest, ServletResponse) which we previously saved in onAccessDenied(ServletRequest, ServletResponse)
      protected void redirectToLogin​(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)
      need custom override, as such AccessControlFilter.getLoginUrl() is ineffective, because we need to construct redirect_uri the utilities of HttpServletResponse.
      protected <T> T retrieveSessionProperty​(javax.servlet.ServletRequest request, java.lang.String key, T defaultValue)  
      protected void saveSessionProperty​(javax.servlet.ServletRequest request, java.lang.String key, java.lang.String value)  
      void setAuthorizeEndpoint​(java.lang.String authorityUrl)
      sets the /authorize endpoint
      void setAuthScope​(java.lang.String authScope)  
      void setClientId​(java.lang.String clientId)  
      void setLoginUrl​(java.lang.String loginUrl)  
      void setOptionalProviderId​(java.lang.String optionalProviderId)  
      void setRedirectUrl​(java.lang.String redirectUrl)  
      void setSuccessUrl​(java.lang.String successUrl)
      override successUrl and dont set a default one, since successUrl is usually a redirectUrl in our case, but in case we provide successUrl this will be explicitly redirected after successful login overriding whatever original url user navigated to
      void setUrlParameterName​(java.lang.String urlParameterName)  
      • Methods inherited from class org.apache.shiro.web.filter.authc.AuthenticatingFilter

        cleanup, createToken, createToken, executeLogin, getHost, isAccessAllowed, isPermissive, isRememberMe, onLoginFailure
      • Methods inherited from class org.apache.shiro.web.filter.authc.AuthenticationFilter

        issueSuccessRedirect
      • Methods inherited from class org.apache.shiro.web.filter.AccessControlFilter

        getLoginUrl, getSubject, onAccessDenied, onPreHandle, saveRequest, saveRequestAndRedirectToLogin
      • Methods inherited from class org.apache.shiro.web.filter.PathMatchingFilter

        getPathWithinApplication, isEnabled, pathsMatch, pathsMatch, preHandle, processPathConfig
      • Methods inherited from class org.apache.shiro.web.servlet.AdviceFilter

        afterCompletion, doFilterInternal, executeChain, postHandle
      • Methods inherited from class org.apache.shiro.web.servlet.OncePerRequestFilter

        doFilter, getAlreadyFilteredAttributeName, isEnabled, setEnabled, shouldNotFilter
      • Methods inherited from class org.apache.shiro.web.servlet.NameableFilter

        getName, setName, toStringBuilder
      • Methods inherited from class org.apache.shiro.web.servlet.AbstractFilter

        destroy, getFilterConfig, getInitParam, init, onFilterConfigSet, setFilterConfig
      • Methods inherited from class org.apache.shiro.web.servlet.ServletContextSupport

        getContextAttribute, getContextInitParam, getServletContext, removeContextAttribute, setContextAttribute, setServletContext, toString
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
    • Field Detail

      • SESSION_ATTR_KEY_AUTH_STATE

        public static final java.lang.String SESSION_ATTR_KEY_AUTH_STATE
        See Also:
        Constant Field Values
      • SESSION_ATTR_KEY_PROVIDER_INSTANCE_ID

        public static final java.lang.String SESSION_ATTR_KEY_PROVIDER_INSTANCE_ID
        See Also:
        Constant Field Values
      • SESSION_ATTR_KEY_ORIG_URL

        public static final java.lang.String SESSION_ATTR_KEY_ORIG_URL
        See Also:
        Constant Field Values
      • clientId

        protected java.lang.String clientId
      • redirectUrl

        protected java.lang.String redirectUrl
      • authorizeEndpoint

        protected java.lang.String authorizeEndpoint
      • urlParameterName

        protected java.lang.String urlParameterName
      • optionalProviderId

        protected java.lang.String optionalProviderId
      • authScope

        protected java.lang.String authScope
      • successUrl

        protected java.lang.String successUrl
    • Constructor Detail

      • OAuthAuthenticatingFilter

        public OAuthAuthenticatingFilter()
    • Method Detail

      • setSuccessUrl

        public void setSuccessUrl​(java.lang.String successUrl)
        override successUrl and dont set a default one, since successUrl is usually a redirectUrl in our case, but in case we provide successUrl this will be explicitly redirected after successful login overriding whatever original url user navigated to
        Overrides:
        setSuccessUrl in class org.apache.shiro.web.filter.authc.AuthenticationFilter
      • getSuccessUrl

        public java.lang.String getSuccessUrl()
        Overrides:
        getSuccessUrl in class org.apache.shiro.web.filter.authc.AuthenticationFilter
      • getClientId

        public java.lang.String getClientId()
      • getAuthorizeEndpoint

        public java.lang.String getAuthorizeEndpoint()
      • setAuthScope

        public void setAuthScope​(java.lang.String authScope)
      • getAuthScope

        public java.lang.String getAuthScope()
        Returns:
        the scope as of oauth2, contains space separated scopes. must not be encoded as it will happen later
      • setAuthorizeEndpoint

        public void setAuthorizeEndpoint​(java.lang.String authorityUrl)
        sets the /authorize endpoint
        Parameters:
        authorityUrl -
      • setRedirectUrl

        public void setRedirectUrl​(java.lang.String redirectUrl)
      • setClientId

        public void setClientId​(java.lang.String clientId)
      • getUrlParameterName

        public java.lang.String getUrlParameterName()
      • getRedirectUrl

        public java.lang.String getRedirectUrl()
      • setUrlParameterName

        public void setUrlParameterName​(java.lang.String urlParameterName)
      • getOptionalProviderId

        public java.lang.String getOptionalProviderId()
      • setOptionalProviderId

        public void setOptionalProviderId​(java.lang.String optionalProviderId)
      • isEnabled

        protected final boolean isEnabled​(javax.servlet.ServletRequest request,
                                          javax.servlet.ServletResponse response)
                                   throws javax.servlet.ServletException,
                                          java.io.IOException
        supports .enable flag and also handles a round-trip from authorization server; in order to provide extend with your logic please override isEnabledByProvider(ServletRequest, ServletResponse)
        Overrides:
        isEnabled in class org.apache.shiro.web.servlet.OncePerRequestFilter
        Throws:
        javax.servlet.ServletException
        java.io.IOException
      • isEnabledByProvider

        protected java.lang.Boolean isEnabledByProvider​(javax.servlet.ServletRequest request,
                                                        javax.servlet.ServletResponse response)
        current implementation checks if parameter getUrlParameterName() equals to getOptionalProviderId(). You can override this method to provide different recognition, i.e. if specific HTTP header is set (i.e. by proxy)
        Parameters:
        request -
        response -
        Returns:
        true to enable processing, false to disable processing or null to delegate decision further
      • setLoginUrl

        public void setLoginUrl​(java.lang.String loginUrl)
        Overrides:
        setLoginUrl in class org.apache.shiro.web.filter.AccessControlFilter
      • constructRedirectUrl

        protected java.lang.String constructRedirectUrl​(javax.servlet.ServletRequest request,
                                                        javax.servlet.ServletResponse response)
                                                 throws java.io.IOException
        Parameters:
        request -
        response -
        Returns:
        either configured redirectUrl or construct one to the context; currently .redirectUrl must be provided
        Throws:
        java.io.UnsupportedEncodingException
        java.io.IOException
      • redirectToLogin

        protected final void redirectToLogin​(javax.servlet.ServletRequest request,
                                             javax.servlet.ServletResponse response)
                                      throws java.io.IOException
        need custom override, as such AccessControlFilter.getLoginUrl() is ineffective, because we need to construct redirect_uri the utilities of HttpServletResponse. This method uses constructLoginUrl(ServletRequest, ServletResponse) to create a login url to authority.
        Overrides:
        redirectToLogin in class org.apache.shiro.web.filter.AccessControlFilter
        Parameters:
        request -
        response -
        Throws:
        java.io.IOException
      • constructLoginUrl

        protected java.lang.String constructLoginUrl​(javax.servlet.ServletRequest request,
                                                     javax.servlet.ServletResponse response)
                                              throws java.io.IOException
        This method basically knows how to construct a login url to authority and delegate creation of redirect_uri to constructRedirectUrl(ServletRequest, ServletResponse).
        Parameters:
        request -
        response -
        Returns:
        URL to be used for login
        Throws:
        java.io.IOException
      • createToken

        protected org.apache.shiro.authc.AuthenticationToken createToken​(javax.servlet.ServletRequest request,
                                                                         javax.servlet.ServletResponse response)
                                                                  throws java.lang.Exception
        Specified by:
        createToken in class org.apache.shiro.web.filter.authc.AuthenticatingFilter
        Returns:
        authentication token which is used by AuthenticatingFilter.executeLogin(ServletRequest, ServletResponse) method
        Throws:
        java.lang.Exception
      • onLoginSuccess

        protected final boolean onLoginSuccess​(org.apache.shiro.authc.AuthenticationToken token,
                                               org.apache.shiro.subject.Subject subject,
                                               javax.servlet.ServletRequest request,
                                               javax.servlet.ServletResponse response)
                                        throws java.lang.Exception
        delegate here to AuthenticationFilter.issueSuccessRedirect(ServletRequest, ServletResponse) which we previously saved in onAccessDenied(ServletRequest, ServletResponse)
        Overrides:
        onLoginSuccess in class org.apache.shiro.web.filter.authc.AuthenticatingFilter
        Throws:
        java.lang.Exception
      • isLoginRequest

        protected boolean isLoginRequest​(javax.servlet.ServletRequest request,
                                         javax.servlet.ServletResponse response)
        according to redirect_url set previously in redirectToLogin(ServletRequest, ServletResponse)
        Overrides:
        isLoginRequest in class org.apache.shiro.web.filter.AccessControlFilter
        Parameters:
        request -
        response -
        Returns:
        true if this is a login request
      • retrieveSessionProperty

        protected <T> T retrieveSessionProperty​(javax.servlet.ServletRequest request,
                                                java.lang.String key,
                                                T defaultValue)
      • saveSessionProperty

        protected void saveSessionProperty​(javax.servlet.ServletRequest request,
                                           java.lang.String key,
                                           java.lang.String value)
      • createStateValue

        protected java.lang.String createStateValue()
        creates a state value used to prevent CRSF. this implementation creates UUID
      • onAccessDenied

        protected final boolean onAccessDenied​(javax.servlet.ServletRequest request,
                                               javax.servlet.ServletResponse response)
                                        throws java.lang.Exception
        handle AccessControlFilter.saveRequestAndRedirectToLogin(ServletRequest, ServletResponse) and redirection to authorization server, in addition creates a state, which is checked in isLoginRequest(ServletRequest, ServletResponse) to prevent CSRF and used in constructLoginUrl(ServletRequest, ServletResponse) to serialize a state to URL
        Specified by:
        onAccessDenied in class org.apache.shiro.web.filter.AccessControlFilter
        Throws:
        java.lang.Exception