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:
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)- shiro asks
AuthenticatingFilter.isAccessAllowed(ServletRequest, ServletResponse, Object)
, which is false if subject is not authenticated -
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 - 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 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
- whenever permission are checked, Shiro scans next realms to authorize, here our jdbcrealm loads properties from database according to prinpical (user-id)
- the
onLoginSuccess(AuthenticationToken, Subject, ServletRequest, ServletResponse)
is overriden 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.
-
-
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.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
-
-
Constructor Summary
Constructors Constructor Description OAuthAuthenticatingFilter()
-
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 toconstructRedirectUrl(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 UUIDprotected 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 overrideisEnabledByProvider(ServletRequest, ServletResponse)
protected java.lang.Boolean
isEnabledByProvider(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)
current implementation checks if parametergetUrlParameterName()
equals togetOptionalProviderId()
.protected boolean
isLoginRequest(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)
according to redirect_url set previously inredirectToLogin(ServletRequest, ServletResponse)
protected boolean
onAccessDenied(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)
handleAccessControlFilter.saveRequestAndRedirectToLogin(ServletRequest, ServletResponse)
and redirection to authorization server, in addition creates a state, which is checked inisLoginRequest(ServletRequest, ServletResponse)
to prevent CSRF and used inconstructLoginUrl(ServletRequest, ServletResponse)
to serialize a state to URLprotected boolean
onLoginSuccess(org.apache.shiro.authc.AuthenticationToken token, org.apache.shiro.subject.Subject subject, javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)
delegate here toAuthenticationFilter.issueSuccessRedirect(ServletRequest, ServletResponse)
which we previously saved inonAccessDenied(ServletRequest, ServletResponse)
protected void
redirectToLogin(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)
need custom override, as suchAccessControlFilter.getLoginUrl()
is ineffective, because we need to construct redirect_uri the utilities ofHttpServletResponse
.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 endpointvoid
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 tovoid
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
-
-
-
-
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
-
-
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 classorg.apache.shiro.web.filter.authc.AuthenticationFilter
-
getSuccessUrl
public java.lang.String getSuccessUrl()
- Overrides:
getSuccessUrl
in classorg.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 overrideisEnabledByProvider(ServletRequest, ServletResponse)
- Overrides:
isEnabled
in classorg.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 parametergetUrlParameterName()
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
public void setLoginUrl(java.lang.String loginUrl)
- Overrides:
setLoginUrl
in classorg.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 suchAccessControlFilter.getLoginUrl()
is ineffective, because we need to construct redirect_uri the utilities ofHttpServletResponse
. This method usesconstructLoginUrl(ServletRequest, ServletResponse)
to create a login url to authority.- Overrides:
redirectToLogin
in classorg.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 toconstructRedirectUrl(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 classorg.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 toAuthenticationFilter.issueSuccessRedirect(ServletRequest, ServletResponse)
which we previously saved inonAccessDenied(ServletRequest, ServletResponse)
- Overrides:
onLoginSuccess
in classorg.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 inredirectToLogin(ServletRequest, ServletResponse)
- Overrides:
isLoginRequest
in classorg.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
handleAccessControlFilter.saveRequestAndRedirectToLogin(ServletRequest, ServletResponse)
and redirection to authorization server, in addition creates a state, which is checked inisLoginRequest(ServletRequest, ServletResponse)
to prevent CSRF and used inconstructLoginUrl(ServletRequest, ServletResponse)
to serialize a state to URL- Specified by:
onAccessDenied
in classorg.apache.shiro.web.filter.AccessControlFilter
- Throws:
java.lang.Exception
-
-