Class OAuthAuthenticatingFilter
java.lang.Object
org.apache.shiro.web.servlet.ServletContextSupport
org.apache.shiro.web.servlet.AbstractFilter
org.apache.shiro.web.servlet.NameableFilter
org.apache.shiro.web.servlet.OncePerRequestFilter
org.apache.shiro.web.servlet.AdviceFilter
org.apache.shiro.web.filter.PathMatchingFilter
org.apache.shiro.web.filter.AccessControlFilter
org.apache.shiro.web.filter.authc.AuthenticationFilter
org.apache.shiro.web.filter.authc.AuthenticatingFilter
de.businesscode.bcdui.subjectsettings.oauth2.OAuthAuthenticatingFilter
- All Implemented Interfaces:
jakarta.servlet.Filter
,org.apache.shiro.lang.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)
- Shiro asks
AuthenticatingFilter.isAccessAllowed(ServletRequest, ServletResponse, Object)
, which is false if subject is not authenticated onAccessDenied(ServletRequest, ServletResponse)
is called in unauthenticated case, here we detect if this a pending login-attempt (round-trip 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- OAuth server responses with "code" http parameter, as so
isLoginRequest(ServletRequest, ServletResponse)
returns true here, as suchonAccessDenied(ServletRequest, ServletResponse)
triggersAuthenticatingFilter.executeLogin(ServletRequest, ServletResponse)
AuthenticatingFilter.executeLogin(ServletRequest, ServletResponse)
queriescreateToken(ServletRequest, ServletResponse)
to create a token (which here is basically the auth-code we got from AD), this token is passed toSubject.login(AuthenticationToken)
- Shiro kicks in and asks each and every available 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 principal. No authorization is done on this level, just authentication, as such our oauth2 realm is authenticating only, and not authorizing
- whenever permission are checked, Shiro scans next realms to authorize, here our JdbcRealm loads properties from database according to principal (user-id)
- the
onLoginSuccess(AuthenticationToken, Subject, ServletRequest, ServletResponse)
is overridden as to delegate toAuthenticationFilter.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.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprotected class
Context of currently ongoing oAuth authentication flows (from selecting authenticate with oauth until success or failure) Since strict cookies are not send on redirects and flex not on posts, we cannot use Shiro's session level way of keeping this but use ehcache insteadstatic enum
-
Field Summary
FieldsModifier and TypeFieldDescriptionprotected String
protected String
protected String
protected String
protected OAuthAuthenticatingFilter.RESPONSE_MODE
protected String
protected final SecureRandom
protected String
protected static final String
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
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected String
protected org.apache.shiro.authc.AuthenticationToken
createToken
(jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) AuthenticatingFilter.createToken(jakarta.servlet.ServletRequest, jakarta.servlet.ServletResponse)
protected String
getRedirectUri
(jakarta.servlet.http.HttpServletRequest request) Unless configured in shiro.ini, we use the current requests base url + /oauth.getScope()
protected final boolean
isEnabled
(jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) supports .enable flag and also handles a round-trip from authorization server; in order to provide extend with your logic please overrideisEnabledByProvider(ServletRequest, ServletResponse)
protected Boolean
isEnabledByProvider
(jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) current implementation checks if parameter URL_PARAMETER_NAME equals togetOptionalProviderId()
.protected boolean
isLoginRequest
(jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) according to redirect_url set previously inredirectToLogin(ServletRequest, ServletResponse)
protected boolean
onAccessDenied
(jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) 1. handles internal Shiro flow.protected boolean
onLoginFailure
(org.apache.shiro.authc.AuthenticationToken token, org.apache.shiro.authc.AuthenticationException e, jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) Handles the failure scenario for a login attempt.protected boolean
onLoginSuccess
(org.apache.shiro.authc.AuthenticationToken token, org.apache.shiro.subject.Subject subject, jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) User authenticated successfully against oAuth and is redirected to our pup-up, which then informs its opener, usually login.html, to redirect to the target URL originally addressedprotected void
redirectToLogin
(jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) 2. createsOAuthAuthenticatingFilter.RequestContext
and sends http/302 with redirection to authority which will take over the authenticationvoid
setAuthorizeEndpoint
(String authorityUrl) void
setClientId
(String clientId) void
setLoginUrl
(String loginUrl) void
setOptionalProviderId
(String optionalProviderId) void
setRedirectUri
(String redirectUri) Optionally hard-wire redirectUri in shiro.ini If not set it is derived from the servlet context (http(s)://myserver.com/ctsPath/oauth)void
setResponseMode
(String responseMode) void
void
setSuccessUrl
(String successUrl) Methods inherited from class org.apache.shiro.web.filter.authc.AuthenticatingFilter
cleanup, createToken, createToken, executeLogin, getHost, isAccessAllowed, isPermissive, isRememberMe
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, isFilterOncePerRequest, setEnabled, setFilterOncePerRequest, 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
-
Field Details
-
URL_PARAMETER_NAME
- See Also:
-
secureRandom
-
clientId
-
redirectUri
-
authorizeEndpoint
-
optionalProviderId
-
scope
-
successUrl
-
responseMode
-
-
Constructor Details
-
OAuthAuthenticatingFilter
public OAuthAuthenticatingFilter()
-
-
Method Details
-
getProviderInstanceId
- Returns:
- the id of this instance
-
setSuccessUrl
- Overrides:
setSuccessUrl
in classorg.apache.shiro.web.filter.authc.AuthenticationFilter
-
getSuccessUrl
- Overrides:
getSuccessUrl
in classorg.apache.shiro.web.filter.authc.AuthenticationFilter
-
setResponseMode
-
getClientId
-
getAuthorizeEndpoint
-
setScope
-
getScope
-
setRedirectUri
Optionally hard-wire redirectUri in shiro.ini If not set it is derived from the servlet context (http(s)://myserver.com/ctsPath/oauth)- Parameters:
redirectUri
-
-
getRedirectUri
Unless configured in shiro.ini, we use the current requests base url + /oauth. Make sure, all values that can show up here are configured at the oAuth authorization server -
setAuthorizeEndpoint
-
setClientId
-
getOptionalProviderId
-
setOptionalProviderId
-
isEnabled
protected final boolean isEnabled(jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) throws jakarta.servlet.ServletException, IOException supports .enable flag and also handles a round-trip from authorization server; in order to provide extend with your logic please overrideisEnabledByProvider(ServletRequest, ServletResponse)
- Overrides:
isEnabled
in classorg.apache.shiro.web.servlet.OncePerRequestFilter
- Throws:
jakarta.servlet.ServletException
IOException
-
isEnabledByProvider
protected Boolean isEnabledByProvider(jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) current implementation checks if parameter URL_PARAMETER_NAME equals togetOptionalProviderId()
. 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
- Overrides:
setLoginUrl
in classorg.apache.shiro.web.filter.AccessControlFilter
-
redirectToLogin
protected void redirectToLogin(jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) throws IOException 2. createsOAuthAuthenticatingFilter.RequestContext
and sends http/302 with redirection to authority which will take over the authentication- Overrides:
redirectToLogin
in classorg.apache.shiro.web.filter.AccessControlFilter
- Parameters:
request
-response
-- Throws:
IOException
- in case the redirect fails
-
createToken
protected org.apache.shiro.authc.AuthenticationToken createToken(jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) throws Exception AuthenticatingFilter.createToken(jakarta.servlet.ServletRequest, jakarta.servlet.ServletResponse)
- Specified by:
createToken
in classorg.apache.shiro.web.filter.authc.AuthenticatingFilter
- Returns:
- authentication token which is used by
AuthenticatingFilter.executeLogin(ServletRequest, ServletResponse)
method - Throws:
Exception
-
onLoginSuccess
protected boolean onLoginSuccess(org.apache.shiro.authc.AuthenticationToken token, org.apache.shiro.subject.Subject subject, jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) throws Exception User authenticated successfully against oAuth and is redirected to our pup-up, which then informs its opener, usually login.html, to redirect to the target URL originally addressed- Overrides:
onLoginSuccess
in classorg.apache.shiro.web.filter.authc.AuthenticatingFilter
- Throws:
Exception
-
onLoginFailure
protected boolean onLoginFailure(org.apache.shiro.authc.AuthenticationToken token, org.apache.shiro.authc.AuthenticationException e, jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) Handles the failure scenario for a login attempt. IWe provides a response indicating the login failure to the user.- Overrides:
onLoginFailure
in classorg.apache.shiro.web.filter.authc.AuthenticatingFilter
- Parameters:
token
- the authentication token used during the login attempte
- the authentication exception that caused the login failurerequest
- the servlet request containing details of the login attemptresponse
- the servlet response object to send feedback to the client- Returns:
- always returns false to indicate the login attempt has failed
-
isLoginRequest
protected boolean isLoginRequest(jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) according to redirect_url set previously inredirectToLogin(ServletRequest, ServletResponse)
- Overrides:
isLoginRequest
in classorg.apache.shiro.web.filter.AccessControlFilter
- Parameters:
request
-response
-- Returns:
- true if this is a login request
-
onAccessDenied
protected boolean onAccessDenied(jakarta.servlet.ServletRequest request, jakarta.servlet.ServletResponse response) throws Exception 1. handles internal Shiro flow. It the request is an incoming request redirected from authorization-server, performAuthenticatingFilter.executeLogin(ServletRequest, ServletResponse)
, otherwiseredirectToLogin(ServletRequest, ServletResponse)
- Specified by:
onAccessDenied
in classorg.apache.shiro.web.filter.AccessControlFilter
- Throws:
Exception
-
createRandomString
- Returns:
- random code, which can be used as code_verifier, base64url encoded
-